diff --git a/CMakeLists.txt b/CMakeLists.txt index d7b0a9d844..70541ab458 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,11 +280,11 @@ set(kwin_XCB_LIBS ${XCB_RENDER_LIBRARY} ${XCB_RANDR_LIBRARY} ${XCB_KEYSYMS_LIBRARY} + ${XCB_SHM_LIBRARY} ) set(kwin_WAYLAND_LIBS ${WAYLAND_CLIENT_LIBRARIES} - ${XCB_SHM_LIBRARY} ${XCB_XTEST_LIBRARY} ) diff --git a/egl_wayland_backend.cpp b/egl_wayland_backend.cpp index fcca068dcc..4d4e0a5298 100644 --- a/egl_wayland_backend.cpp +++ b/egl_wayland_backend.cpp @@ -22,15 +22,13 @@ along with this program. If not, see . // kwin #include "options.h" #include "wayland_backend.h" +#include "xcbutils.h" // kwin libs #include // KDE #include // Qt #include -// system -#include -#include namespace KWin { @@ -327,10 +325,10 @@ void EglWaylandBackend::doneCurrent() eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } -Shm *EglWaylandBackend::shm() +Xcb::Shm *EglWaylandBackend::shm() { if (m_shm.isNull()) { - m_shm.reset(new Shm); + m_shm.reset(new Xcb::Shm); } return m_shm.data(); } @@ -380,7 +378,7 @@ bool EglWaylandTexture::loadTexture(const Pixmap &pix, const QSize &size, int de return false; m_referencedPixmap = pix; - Shm *shm = m_backend->shm(); + Xcb::Shm *shm = m_backend->shm(); if (!shm->isValid()) { return false; } @@ -418,7 +416,7 @@ bool EglWaylandTexture::update(const QRegion &damage) return false; } - Shm *shm = m_backend->shm(); + Xcb::Shm *shm = m_backend->shm(); if (!shm->isValid()) { return false; } @@ -446,60 +444,4 @@ bool EglWaylandTexture::update(const QRegion &damage) return true; } -Shm::Shm() - : m_shmId(-1) - , m_buffer(NULL) - , m_segment(XCB_NONE) - , m_valid(false) -{ - m_valid = init(); -} - -Shm::~Shm() -{ - if (m_valid) { - xcb_shm_detach(connection(), m_segment); - shmdt(m_buffer); - } -} - -bool Shm::init() -{ - const xcb_query_extension_reply_t *ext = xcb_get_extension_data(connection(), &xcb_shm_id); - if (!ext || !ext->present) { - qDebug() << "SHM extension not available"; - return false; - } - ScopedCPointer version(xcb_shm_query_version_reply(connection(), - xcb_shm_query_version_unchecked(connection()), NULL)); - if (version.isNull()) { - qDebug() << "Failed to get SHM extension version information"; - return false; - } - const int MAXSIZE = 4096 * 2048 * 4; // TODO check there are not larger windows - m_shmId = shmget(IPC_PRIVATE, MAXSIZE, IPC_CREAT | 0600); - if (m_shmId < 0) { - qDebug() << "Failed to allocate SHM segment"; - return false; - } - m_buffer = shmat(m_shmId, NULL, 0 /*read/write*/); - if (-1 == reinterpret_cast(m_buffer)) { - qDebug() << "Failed to attach SHM segment"; - shmctl(m_shmId, IPC_RMID, NULL); - return false; - } - shmctl(m_shmId, IPC_RMID, NULL); - - m_segment = xcb_generate_id(connection()); - const xcb_void_cookie_t cookie = xcb_shm_attach_checked(connection(), m_segment, m_shmId, false); - ScopedCPointer error(xcb_request_check(connection(), cookie)); - if (!error.isNull()) { - qDebug() << "xcb_shm_attach error: " << error->error_code; - shmdt(m_buffer); - return false; - } - - return true; -} - } // namespace diff --git a/egl_wayland_backend.h b/egl_wayland_backend.h index 84eace92c6..6c5ac39d53 100644 --- a/egl_wayland_backend.h +++ b/egl_wayland_backend.h @@ -22,8 +22,6 @@ along with this program. If not, see . #include "scene_opengl.h" // wayland #include -// xcb -#include class QTemporaryFile; struct wl_buffer; @@ -36,7 +34,9 @@ namespace Wayland { class WaylandBackend; } -class Shm; +namespace Xcb { + class Shm; +} /** * @brief OpenGL Backend using Egl on a Wayland surface. @@ -66,7 +66,7 @@ public: virtual void endRenderingFrame(const QRegion &renderedRegion, const QRegion &damagedRegion); virtual bool makeCurrent() override; virtual void doneCurrent() override; - Shm *shm(); + Xcb::Shm *shm(); protected: virtual void present(); @@ -87,7 +87,7 @@ private: int m_bufferAge; Wayland::WaylandBackend *m_wayland; wl_egl_window *m_overlay; - QScopedPointer m_shm; + QScopedPointer m_shm; friend class EglWaylandTexture; }; @@ -114,51 +114,6 @@ private: xcb_pixmap_t m_referencedPixmap; }; -/** - * @brief Small helper class to encapsulate SHM related functionality. - * - */ -class Shm -{ -public: - Shm(); - ~Shm(); - int shmId() const; - void *buffer() const; - xcb_shm_seg_t segment() const; - bool isValid() const; -private: - bool init(); - int m_shmId; - void *m_buffer; - xcb_shm_seg_t m_segment; - bool m_valid; -}; - -inline -void *Shm::buffer() const -{ - return m_buffer; -} - -inline -bool Shm::isValid() const -{ - return m_valid; -} - -inline -xcb_shm_seg_t Shm::segment() const -{ - return m_segment; -} - -inline -int Shm::shmId() const -{ - return m_shmId; -} - } // namespace #endif // KWIN_EGL_ON_X_BACKEND_H diff --git a/xcbutils.cpp b/xcbutils.cpp index a287c3ca38..5bff1de8f2 100644 --- a/xcbutils.cpp +++ b/xcbutils.cpp @@ -30,6 +30,9 @@ along with this program. If not, see . #include #include #include +// system +#include +#include namespace KWin { @@ -254,5 +257,64 @@ QVector Extensions::extensions() const return extensions; } +//**************************************** +// Shm +//**************************************** +Shm::Shm() + : m_shmId(-1) + , m_buffer(NULL) + , m_segment(XCB_NONE) + , m_valid(false) +{ + m_valid = init(); +} + +Shm::~Shm() +{ + if (m_valid) { + xcb_shm_detach(connection(), m_segment); + shmdt(m_buffer); + } +} + +bool Shm::init() +{ + const xcb_query_extension_reply_t *ext = xcb_get_extension_data(connection(), &xcb_shm_id); + if (!ext || !ext->present) { + qDebug() << "SHM extension not available"; + return false; + } + ScopedCPointer version(xcb_shm_query_version_reply(connection(), + xcb_shm_query_version_unchecked(connection()), NULL)); + if (version.isNull()) { + qDebug() << "Failed to get SHM extension version information"; + return false; + } + const int MAXSIZE = 4096 * 2048 * 4; // TODO check there are not larger windows + m_shmId = shmget(IPC_PRIVATE, MAXSIZE, IPC_CREAT | 0600); + if (m_shmId < 0) { + qDebug() << "Failed to allocate SHM segment"; + return false; + } + m_buffer = shmat(m_shmId, NULL, 0 /*read/write*/); + if (-1 == reinterpret_cast(m_buffer)) { + qDebug() << "Failed to attach SHM segment"; + shmctl(m_shmId, IPC_RMID, NULL); + return false; + } + shmctl(m_shmId, IPC_RMID, NULL); + + m_segment = xcb_generate_id(connection()); + const xcb_void_cookie_t cookie = xcb_shm_attach_checked(connection(), m_segment, m_shmId, false); + ScopedCPointer error(xcb_request_check(connection(), cookie)); + if (!error.isNull()) { + qDebug() << "xcb_shm_attach error: " << error->error_code; + shmdt(m_buffer); + return false; + } + + return true; +} + } // namespace Xcb } // namespace KWin diff --git a/xcbutils.h b/xcbutils.h index 6c44920be0..4ce56eac25 100644 --- a/xcbutils.h +++ b/xcbutils.h @@ -31,6 +31,8 @@ along with this program. If not, see . #include #include +#include + namespace KWin { namespace Xcb { @@ -908,6 +910,51 @@ void selectInput(xcb_window_t window, uint32_t events) xcb_change_window_attributes(connection(), window, XCB_CW_EVENT_MASK, &events); } +/** + * @brief Small helper class to encapsulate SHM related functionality. + * + */ +class Shm +{ +public: + Shm(); + ~Shm(); + int shmId() const; + void *buffer() const; + xcb_shm_seg_t segment() const; + bool isValid() const; +private: + bool init(); + int m_shmId; + void *m_buffer; + xcb_shm_seg_t m_segment; + bool m_valid; +}; + +inline +void *Shm::buffer() const +{ + return m_buffer; +} + +inline +bool Shm::isValid() const +{ + return m_valid; +} + +inline +xcb_shm_seg_t Shm::segment() const +{ + return m_segment; +} + +inline +int Shm::shmId() const +{ + return m_shmId; +} + } // namespace X11 } // namespace KWin