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; }