diff --git a/scene.cpp b/scene.cpp
index 94eeba1cdc..37e1c3a42b 100644
--- a/scene.cpp
+++ b/scene.cpp
@@ -81,6 +81,11 @@ along with this program. If not, see .
#include "thumbnailitem.h"
#include "workspace.h"
+#if HAVE_WAYLAND
+#include
+#include
+#endif
+
namespace KWin
{
@@ -928,7 +933,7 @@ WindowPixmap::WindowPixmap(Scene::Window *window)
WindowPixmap::~WindowPixmap()
{
- if (isValid()) {
+ if (isValid() && !kwinApp()->shouldUseWaylandForCompositing()) {
xcb_free_pixmap(connection(), m_pixmap);
}
}
@@ -938,6 +943,16 @@ void WindowPixmap::create()
if (isValid() || toplevel()->isDeleted()) {
return;
}
+#if HAVE_WAYLAND
+ if (kwinApp()->shouldUseWaylandForCompositing()) {
+ // use Buffer
+ updateBuffer();
+ if (m_buffer) {
+ m_window->unreferencePreviousPixmap();
+ }
+ return;
+ }
+#endif
XServerGrabber grabber;
xcb_pixmap_t pix = xcb_generate_id(connection());
xcb_void_cookie_t namePixmapCookie = xcb_composite_name_window_pixmap_checked(connection(), toplevel()->frameId(), pix);
@@ -967,6 +982,27 @@ void WindowPixmap::create()
m_window->unreferencePreviousPixmap();
}
+bool WindowPixmap::isValid() const
+{
+#if HAVE_WAYLAND
+ if (kwinApp()->shouldUseWaylandForCompositing()) {
+ return !m_buffer.isNull();
+ }
+#endif
+ return m_pixmap != XCB_PIXMAP_NONE;
+}
+
+#if HAVE_WAYLAND
+void WindowPixmap::updateBuffer()
+{
+ if (auto s = toplevel()->surface()) {
+ if (auto b = s->buffer()) {
+ m_buffer = b;
+ }
+ }
+}
+#endif
+
//****************************************
// Scene::EffectFrame
//****************************************
diff --git a/scene.h b/scene.h
index f6f5322481..4d23660758 100644
--- a/scene.h
+++ b/scene.h
@@ -27,6 +27,16 @@ along with this program. If not, see .
#include
+#if HAVE_WAYLAND
+namespace KWayland
+{
+namespace Server
+{
+class BufferInterface;
+}
+}
+#endif
+
namespace KWin
{
@@ -345,6 +355,12 @@ public:
* @return The native X11 pixmap handle
*/
xcb_pixmap_t pixmap() const;
+#if HAVE_WAYLAND
+ /**
+ * @return The Wayland BufferInterface for this WindowPixmap.
+ **/
+ QPointer buffer() const;
+#endif
/**
* @brief Whether this WindowPixmap is considered as discarded. This means the window has changed in a way that a new
* WindowPixmap should have been created already.
@@ -382,12 +398,23 @@ protected:
* @return The Window this WindowPixmap belongs to
*/
Scene::Window *window();
+
+#if HAVE_WAYLAND
+ /**
+ * Should be called by the implementing subclasses when the Wayland Buffer changed and needs
+ * updating.
+ **/
+ void updateBuffer();
+#endif
private:
Scene::Window *m_window;
xcb_pixmap_t m_pixmap;
QSize m_pixmapSize;
bool m_discarded;
QRect m_contentsRect;
+#if HAVE_WAYLAND
+ QPointer m_buffer;
+#endif
};
class Scene::EffectFrame
@@ -491,11 +518,13 @@ Shadow* Scene::Window::shadow()
return m_shadow;
}
+#if HAVE_WAYLAND
inline
-bool WindowPixmap::isValid() const
+QPointer WindowPixmap::buffer() const
{
- return m_pixmap != XCB_PIXMAP_NONE;
+ return m_buffer;
}
+#endif
template
inline
diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp
index 56e7cbb43d..1f21755885 100644
--- a/scene_qpainter.cpp
+++ b/scene_qpainter.cpp
@@ -30,6 +30,8 @@ along with this program. If not, see .
#include
#include
#include
+#include
+#include
#endif
#include "workspace.h"
#include "xcbutils.h"
@@ -461,7 +463,7 @@ Decoration::Renderer *SceneQPainter::createDecorationRenderer(Decoration::Decora
//****************************************
QPainterWindowPixmap::QPainterWindowPixmap(Scene::Window *window)
: WindowPixmap(window)
- , m_shm(new Xcb::Shm)
+ , m_shm(kwinApp()->shouldUseWaylandForCompositing() ? nullptr : new Xcb::Shm)
{
}
@@ -471,19 +473,46 @@ QPainterWindowPixmap::~QPainterWindowPixmap()
void QPainterWindowPixmap::create()
{
- if (isValid() || !m_shm->isValid()) {
+ if (isValid()) {
+ return;
+ }
+ if (!kwinApp()->shouldUseWaylandForCompositing() && !m_shm->isValid()) {
return;
}
KWin::WindowPixmap::create();
if (!isValid()) {
return;
}
+#if HAVE_WAYLAND
+ if (kwinApp()->shouldUseWaylandForCompositing()) {
+ // performing deep copy, this could probably be improved
+ m_image = buffer()->data().copy();
+ return;
+ }
+#endif
m_image = QImage((uchar*)m_shm->buffer(), size().width(), size().height(), QImage::Format_ARGB32_Premultiplied);
}
bool QPainterWindowPixmap::update(const QRegion &damage)
{
- Q_UNUSED(damage)
+#if HAVE_WAYLAND
+ if (kwinApp()->shouldUseWaylandForCompositing()) {
+ const auto oldBuffer = buffer();
+ updateBuffer();
+ const auto &b = buffer();
+ if (b == oldBuffer || b.isNull()) {
+ return false;
+ }
+ QPainter p(&m_image);
+ const QImage &data = b->data();
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ for (const QRect &rect : damage.rects()) {
+ p.drawImage(rect, data, rect);
+ }
+ return true;
+ }
+#endif
+
if (!m_shm->isValid()) {
return false;
}