diff --git a/platform.cpp b/platform.cpp index 293f6fa360..926bf2e059 100644 --- a/platform.cpp +++ b/platform.cpp @@ -90,6 +90,11 @@ QPainterBackend *Platform::createQPainterBackend() return nullptr; } +XRenderBackend *Platform::createXRenderBackend() +{ + return nullptr; +} + void Platform::prepareShutdown() { setOutputsEnabled(false); diff --git a/platform.h b/platform.h index 8395e6663d..ae490752da 100644 --- a/platform.h +++ b/platform.h @@ -42,6 +42,7 @@ class Scene; class Screens; class ScreenEdges; class Toplevel; +class XRenderBackend; namespace Decoration { @@ -70,6 +71,7 @@ public: virtual Screens *createScreens(QObject *parent = nullptr); virtual OpenGLBackend *createOpenGLBackend(); virtual QPainterBackend *createQPainterBackend(); + virtual XRenderBackend *createXRenderBackend(); virtual DmaBufTexture *createDmaBufTexture(const QSize &size) { Q_UNUSED(size); return nullptr; diff --git a/platformsupport/scenes/CMakeLists.txt b/platformsupport/scenes/CMakeLists.txt index 6e560cbcda..c3b0b166a0 100644 --- a/platformsupport/scenes/CMakeLists.txt +++ b/platformsupport/scenes/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(qpainter) add_subdirectory(opengl) +add_subdirectory(xrender) diff --git a/platformsupport/scenes/xrender/CMakeLists.txt b/platformsupport/scenes/xrender/CMakeLists.txt new file mode 100644 index 0000000000..bbe7d7381a --- /dev/null +++ b/platformsupport/scenes/xrender/CMakeLists.txt @@ -0,0 +1,11 @@ +set(xrenderbackend_SOURCES xrenderbackend.cpp) + +ecm_qt_declare_logging_category(xrenderbackend_SOURCES + HEADER logging.h + IDENTIFIER KWIN_XRENDER + CATEGORY_NAME kwin_scene_xrender + DEFAULT_SEVERITY Critical +) + +add_library(SceneXRenderBackend STATIC ${xrenderbackend_SOURCES}) +target_link_libraries(SceneXRenderBackend kwin Qt5::Core Qt5::Gui) diff --git a/platformsupport/scenes/xrender/xrenderbackend.cpp b/platformsupport/scenes/xrender/xrenderbackend.cpp new file mode 100644 index 0000000000..b9042f3e93 --- /dev/null +++ b/platformsupport/scenes/xrender/xrenderbackend.cpp @@ -0,0 +1,78 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2006 Lubos Lunak + SPDX-FileCopyrightText: 2009 Fredrik Höglund + SPDX-FileCopyrightText: 2013 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "xrenderbackend.h" +#include "logging.h" +#include "xcbutils.h" + +namespace KWin +{ + +XRenderBackend::XRenderBackend() + : m_buffer(XCB_RENDER_PICTURE_NONE) + , m_failed(false) +{ + if (!Xcb::Extensions::self()->isRenderAvailable()) { + setFailed("No XRender extension available"); + return; + } + if (!Xcb::Extensions::self()->isFixesRegionAvailable()) { + setFailed("No XFixes v3+ extension available"); + return; + } +} + +XRenderBackend::~XRenderBackend() +{ + if (m_buffer) { + xcb_render_free_picture(connection(), m_buffer); + } +} + +OverlayWindow *XRenderBackend::overlayWindow() +{ + return nullptr; +} + +void XRenderBackend::showOverlay() +{ +} + +xcb_render_picture_t XRenderBackend::buffer() const +{ + return m_buffer; +} + +void XRenderBackend::setBuffer(xcb_render_picture_t buffer) +{ + if (m_buffer != XCB_RENDER_PICTURE_NONE) { + xcb_render_free_picture(connection(), m_buffer); + } + m_buffer = buffer; +} + +bool XRenderBackend::isFailed() const +{ + return m_failed; +} + +void XRenderBackend::setFailed(const QString &reason) +{ + qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " << reason; + m_failed = true; +} + +void XRenderBackend::screenGeometryChanged(const QSize &size) +{ + Q_UNUSED(size) +} + +} // namespace KWin diff --git a/platformsupport/scenes/xrender/xrenderbackend.h b/platformsupport/scenes/xrender/xrenderbackend.h new file mode 100644 index 0000000000..a12a4a17ab --- /dev/null +++ b/platformsupport/scenes/xrender/xrenderbackend.h @@ -0,0 +1,104 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2006 Lubos Lunak + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include +#include + +#include + +namespace KWin +{ + +class OverlayWindow; + +/** + * @brief Backend for the SceneXRender to hold the compositing buffer and take care of buffer + * swapping. + * + * This class is intended as a small abstraction to support multiple compositing backends in the + * SceneXRender. + */ +class XRenderBackend +{ +public: + virtual ~XRenderBackend(); + virtual void present(int mask, const QRegion &damage) = 0; + + /** + * @brief Returns the OverlayWindow used by the backend. + * + * A backend does not have to use an OverlayWindow, this is mostly for the X world. + * In case the backend does not use an OverlayWindow it is allowed to return @c null. + * It's the task of the caller to check whether it is @c null. + * + * @return :OverlayWindow* + */ + virtual OverlayWindow *overlayWindow(); + virtual bool usesOverlayWindow() const = 0; + /** + * @brief Shows the Overlay Window + * + * Default implementation does nothing. + */ + virtual void showOverlay(); + /** + * @brief React on screen geometry changes. + * + * Default implementation does nothing. Override if specific functionality is required. + * + * @param size The new screen size + */ + virtual void screenGeometryChanged(const QSize &size); + /** + * @brief The compositing buffer hold by this backend. + * + * The Scene composites the new frame into this buffer. + * + * @return xcb_render_picture_t + */ + xcb_render_picture_t buffer() const; + /** + * @brief Whether the creation of the Backend failed. + * + * The SceneXRender should test whether the Backend got constructed correctly. If this method + * returns @c true, the SceneXRender should not try to start the rendering. + * + * @return bool @c true if the creation of the Backend failed, @c false otherwise. + */ + bool isFailed() const; + +protected: + XRenderBackend(); + /** + * @brief A subclass needs to call this method once it created the compositing back buffer. + * + * @param buffer The buffer to use for compositing + * @return void + */ + void setBuffer(xcb_render_picture_t buffer); + /** + * @brief Sets the backend initialization to failed. + * + * This method should be called by the concrete subclass in case the initialization failed. + * The given @p reason is logged as a warning. + * + * @param reason The reason why the initialization failed. + */ + void setFailed(const QString &reason); + +private: + // Create the compositing buffer. The root window is not double-buffered, + // so it is done manually using this buffer, + xcb_render_picture_t m_buffer; + bool m_failed; +}; + +} // namespace KWin diff --git a/plugins/platforms/x11/standalone/CMakeLists.txt b/plugins/platforms/x11/standalone/CMakeLists.txt index e9dce7a61a..bf7ce30054 100644 --- a/plugins/platforms/x11/standalone/CMakeLists.txt +++ b/plugins/platforms/x11/standalone/CMakeLists.txt @@ -12,6 +12,7 @@ set(X11PLATFORM_SOURCES x11_output.cpp x11_platform.cpp x11cursor.cpp + x11xrenderbackend.cpp xfixes_cursor_event_filter.cpp ) @@ -24,10 +25,11 @@ if (HAVE_EPOXY_GLX) endif() include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/opengl) +include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/xrender) 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 SceneXRenderBackend 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/x11_platform.cpp b/plugins/platforms/x11/standalone/x11_platform.cpp index 0952914f61..2a5e0fc231 100644 --- a/plugins/platforms/x11/standalone/x11_platform.cpp +++ b/plugins/platforms/x11/standalone/x11_platform.cpp @@ -10,6 +10,7 @@ #include "x11cursor.h" #include "edge.h" #include "windowselector.h" +#include "x11xrenderbackend.h" #include #include #if HAVE_EPOXY_GLX @@ -119,6 +120,11 @@ OpenGLBackend *X11StandalonePlatform::createOpenGLBackend() } } +XRenderBackend *X11StandalonePlatform::createXRenderBackend() +{ + return new X11XRenderBackend(this); +} + Edge *X11StandalonePlatform::createScreenEdge(ScreenEdges *edges) { if (m_screenEdgesFilter.isNull()) { diff --git a/plugins/platforms/x11/standalone/x11_platform.h b/plugins/platforms/x11/standalone/x11_platform.h index ed4820e539..7c1fe9d8eb 100644 --- a/plugins/platforms/x11/standalone/x11_platform.h +++ b/plugins/platforms/x11/standalone/x11_platform.h @@ -35,6 +35,7 @@ public: Screens *createScreens(QObject *parent = nullptr) override; OpenGLBackend *createOpenGLBackend() override; + XRenderBackend *createXRenderBackend() override; Edge *createScreenEdge(ScreenEdges *parent) override; void createPlatformCursor(QObject *parent = nullptr) override; bool requiresCompositing() const override; diff --git a/plugins/platforms/x11/standalone/x11xrenderbackend.cpp b/plugins/platforms/x11/standalone/x11xrenderbackend.cpp new file mode 100644 index 0000000000..a4f40e60d9 --- /dev/null +++ b/plugins/platforms/x11/standalone/x11xrenderbackend.cpp @@ -0,0 +1,133 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2006 Lubos Lunak + SPDX-FileCopyrightText: 2009 Fredrik Höglund + SPDX-FileCopyrightText: 2013 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "x11xrenderbackend.h" +#include "main.h" +#include "platform.h" +#include "overlaywindow.h" +#include "scene.h" +#include "screens.h" +#include "utils.h" +#include "x11_platform.h" + +#include "kwinxrenderutils.h" + +namespace KWin +{ + +X11XRenderBackend::X11XRenderBackend(X11StandalonePlatform *backend) + : XRenderBackend() + , m_backend(backend) + , m_overlayWindow(backend->createOverlayWindow()) + , m_front(XCB_RENDER_PICTURE_NONE) + , m_format(0) +{ + init(true); +} + +X11XRenderBackend::~X11XRenderBackend() +{ + if (m_front) { + xcb_render_free_picture(connection(), m_front); + } + m_overlayWindow->destroy(); +} + +OverlayWindow *X11XRenderBackend::overlayWindow() +{ + return m_overlayWindow.data(); +} + +void X11XRenderBackend::showOverlay() +{ + if (m_overlayWindow->window()) { // show the window only after the first pass, since + m_overlayWindow->show(); // that pass may take long + } +} + +void X11XRenderBackend::init(bool createOverlay) +{ + if (m_front != XCB_RENDER_PICTURE_NONE) + xcb_render_free_picture(connection(), m_front); + bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE); + if (haveOverlay) { + m_overlayWindow->setup(XCB_WINDOW_NONE); + ScopedCPointer attribs(xcb_get_window_attributes_reply(connection(), + xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), nullptr)); + if (!attribs) { + setFailed("Failed getting window attributes for overlay window"); + return; + } + m_format = XRenderUtils::findPictFormat(attribs->visual); + if (m_format == 0) { + setFailed("Failed to find XRender format for overlay window"); + return; + } + m_front = xcb_generate_id(connection()); + xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, nullptr); + } else { + // create XRender picture for the root window + m_format = XRenderUtils::findPictFormat(kwinApp()->x11DefaultScreen()->root_visual); + if (m_format == 0) { + setFailed("Failed to find XRender format for root window"); + return; // error + } + m_front = xcb_generate_id(connection()); + const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}; + xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values); + } + createBuffer(); +} + +void X11XRenderBackend::createBuffer() +{ + xcb_pixmap_t pixmap = xcb_generate_id(connection()); + const auto displaySize = screens()->displaySize(); + xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displaySize.width(), displaySize.height()); + xcb_render_picture_t b = xcb_generate_id(connection()); + xcb_render_create_picture(connection(), b, pixmap, m_format, 0, nullptr); + xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now + setBuffer(b); +} + +void X11XRenderBackend::present(int mask, const QRegion &damage) +{ + const auto displaySize = screens()->displaySize(); + if (mask & Scene::PAINT_SCREEN_REGION) { + // Use the damage region as the clip region for the root window + XFixesRegion frontRegion(damage); + xcb_xfixes_set_picture_clip_region(connection(), m_front, frontRegion, 0, 0); + // copy composed buffer to the root window + xcb_xfixes_set_picture_clip_region(connection(), buffer(), XCB_XFIXES_REGION_NONE, 0, 0); + xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, + m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height()); + xcb_xfixes_set_picture_clip_region(connection(), m_front, XCB_XFIXES_REGION_NONE, 0, 0); + } else { + // copy composed buffer to the root window + xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, + m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height()); + } + + xcb_flush(connection()); +} + +void X11XRenderBackend::screenGeometryChanged(const QSize &size) +{ + Q_UNUSED(size) + init(false); +} + +bool X11XRenderBackend::usesOverlayWindow() const +{ + return true; +} + +} // namespace KWin diff --git a/plugins/platforms/x11/standalone/x11xrenderbackend.h b/plugins/platforms/x11/standalone/x11xrenderbackend.h new file mode 100644 index 0000000000..c159548211 --- /dev/null +++ b/plugins/platforms/x11/standalone/x11xrenderbackend.h @@ -0,0 +1,43 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2006 Lubos Lunak + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "xrenderbackend.h" + +namespace KWin +{ + +class X11StandalonePlatform; + +/** + * @brief XRenderBackend using an X11 Overlay Window as compositing target. + */ +class X11XRenderBackend : public XRenderBackend +{ +public: + explicit X11XRenderBackend(X11StandalonePlatform *backend); + ~X11XRenderBackend() override; + + void present(int mask, const QRegion &damage) override; + OverlayWindow *overlayWindow() override; + void showOverlay() override; + void screenGeometryChanged(const QSize &size) override; + bool usesOverlayWindow() const override; + +private: + void init(bool createOverlay); + void createBuffer(); + X11StandalonePlatform *m_backend; + QScopedPointer m_overlayWindow; + xcb_render_picture_t m_front; + xcb_render_pictformat_t m_format; +}; + +} // namespace KWin diff --git a/plugins/scenes/xrender/CMakeLists.txt b/plugins/scenes/xrender/CMakeLists.txt index 2f16fc4cdb..e5be934405 100644 --- a/plugins/scenes/xrender/CMakeLists.txt +++ b/plugins/scenes/xrender/CMakeLists.txt @@ -12,12 +12,11 @@ ecm_qt_declare_logging_category( Critical ) +include_directories(${CMAKE_SOURCE_DIR}/platformsupport/scenes/xrender) + add_library(KWinSceneXRender MODULE ${SCENE_XRENDER_SRCS}) set_target_properties(KWinSceneXRender PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/org.kde.kwin.scenes/") -target_link_libraries(KWinSceneXRender - kwin - kwinxrenderutils -) +target_link_libraries(KWinSceneXRender kwin kwinxrenderutils SceneXRenderBackend) install( TARGETS diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp index 9e29398659..b967fe7350 100644 --- a/plugins/scenes/xrender/scene_xrender.cpp +++ b/plugins/scenes/xrender/scene_xrender.cpp @@ -9,8 +9,8 @@ SPDX-License-Identifier: GPL-2.0-or-later */ #include "scene_xrender.h" - #include "utils.h" +#include "xrenderbackend.h" #ifdef KWIN_HAVE_XRENDER_COMPOSITING @@ -44,177 +44,14 @@ ScreenPaintData SceneXrender::screen_paint; #define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536)) #define FIXED_TO_DOUBLE(f) ((double) ((f) / 65536.0)) - -//**************************************** -// XRenderBackend -//**************************************** -XRenderBackend::XRenderBackend() - : m_buffer(XCB_RENDER_PICTURE_NONE) - , m_failed(false) -{ - if (!Xcb::Extensions::self()->isRenderAvailable()) { - setFailed("No XRender extension available"); - return; - } - if (!Xcb::Extensions::self()->isFixesRegionAvailable()) { - setFailed("No XFixes v3+ extension available"); - return; - } -} - -XRenderBackend::~XRenderBackend() -{ - if (m_buffer) { - xcb_render_free_picture(connection(), m_buffer); - } -} - -OverlayWindow* XRenderBackend::overlayWindow() -{ - return nullptr; -} - -void XRenderBackend::showOverlay() -{ -} - -void XRenderBackend::setBuffer(xcb_render_picture_t buffer) -{ - if (m_buffer != XCB_RENDER_PICTURE_NONE) { - xcb_render_free_picture(connection(), m_buffer); - } - m_buffer = buffer; -} - -void XRenderBackend::setFailed(const QString& reason) -{ - qCCritical(KWIN_XRENDER) << "Creating the XRender backend failed: " << reason; - m_failed = true; -} - -void XRenderBackend::screenGeometryChanged(const QSize &size) -{ - Q_UNUSED(size) -} - - -//**************************************** -// X11XRenderBackend -//**************************************** -X11XRenderBackend::X11XRenderBackend() - : XRenderBackend() - , m_overlayWindow(kwinApp()->platform()->createOverlayWindow()) - , m_front(XCB_RENDER_PICTURE_NONE) - , m_format(0) -{ - init(true); -} - -X11XRenderBackend::~X11XRenderBackend() -{ - if (m_front) { - xcb_render_free_picture(connection(), m_front); - } - m_overlayWindow->destroy(); -} - -OverlayWindow* X11XRenderBackend::overlayWindow() -{ - return m_overlayWindow.data(); -} - -void X11XRenderBackend::showOverlay() -{ - if (m_overlayWindow->window()) // show the window only after the first pass, since - m_overlayWindow->show(); // that pass may take long -} - -void X11XRenderBackend::init(bool createOverlay) -{ - if (m_front != XCB_RENDER_PICTURE_NONE) - xcb_render_free_picture(connection(), m_front); - bool haveOverlay = createOverlay ? m_overlayWindow->create() : (m_overlayWindow->window() != XCB_WINDOW_NONE); - if (haveOverlay) { - m_overlayWindow->setup(XCB_WINDOW_NONE); - ScopedCPointer attribs(xcb_get_window_attributes_reply(connection(), - xcb_get_window_attributes_unchecked(connection(), m_overlayWindow->window()), nullptr)); - if (!attribs) { - setFailed("Failed getting window attributes for overlay window"); - return; - } - m_format = XRenderUtils::findPictFormat(attribs->visual); - if (m_format == 0) { - setFailed("Failed to find XRender format for overlay window"); - return; - } - m_front = xcb_generate_id(connection()); - xcb_render_create_picture(connection(), m_front, m_overlayWindow->window(), m_format, 0, nullptr); - } else { - // create XRender picture for the root window - m_format = XRenderUtils::findPictFormat(kwinApp()->x11DefaultScreen()->root_visual); - if (m_format == 0) { - setFailed("Failed to find XRender format for root window"); - return; // error - } - m_front = xcb_generate_id(connection()); - const uint32_t values[] = {XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS}; - xcb_render_create_picture(connection(), m_front, rootWindow(), m_format, XCB_RENDER_CP_SUBWINDOW_MODE, values); - } - createBuffer(); -} - -void X11XRenderBackend::createBuffer() -{ - xcb_pixmap_t pixmap = xcb_generate_id(connection()); - const auto displaySize = screens()->displaySize(); - xcb_create_pixmap(connection(), Xcb::defaultDepth(), pixmap, rootWindow(), displaySize.width(), displaySize.height()); - xcb_render_picture_t b = xcb_generate_id(connection()); - xcb_render_create_picture(connection(), b, pixmap, m_format, 0, nullptr); - xcb_free_pixmap(connection(), pixmap); // The picture owns the pixmap now - setBuffer(b); -} - -void X11XRenderBackend::present(int mask, const QRegion &damage) -{ - const auto displaySize = screens()->displaySize(); - if (mask & Scene::PAINT_SCREEN_REGION) { - // Use the damage region as the clip region for the root window - XFixesRegion frontRegion(damage); - xcb_xfixes_set_picture_clip_region(connection(), m_front, frontRegion, 0, 0); - // copy composed buffer to the root window - xcb_xfixes_set_picture_clip_region(connection(), buffer(), XCB_XFIXES_REGION_NONE, 0, 0); - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, - m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height()); - xcb_xfixes_set_picture_clip_region(connection(), m_front, XCB_XFIXES_REGION_NONE, 0, 0); - xcb_flush(connection()); - } else { - // copy composed buffer to the root window - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_SRC, buffer(), XCB_RENDER_PICTURE_NONE, - m_front, 0, 0, 0, 0, 0, 0, displaySize.width(), displaySize.height()); - xcb_flush(connection()); - } -} - -void X11XRenderBackend::screenGeometryChanged(const QSize &size) -{ - Q_UNUSED(size) - init(false); -} - -bool X11XRenderBackend::usesOverlayWindow() const -{ - return true; -} - //**************************************** // SceneXrender //**************************************** SceneXrender* SceneXrender::createScene(QObject *parent) { - QScopedPointer backend; - backend.reset(new X11XRenderBackend); - if (backend->isFailed()) { + QScopedPointer backend(kwinApp()->platform()->createXRenderBackend()); + if (!backend || backend->isFailed()) { return nullptr; } return new SceneXrender(backend.take(), parent); @@ -781,6 +618,21 @@ void SceneXrender::screenGeometryChanged(const QSize &size) m_backend->screenGeometryChanged(size); } +xcb_render_picture_t SceneXrender::xrenderBufferPicture() const +{ + return m_backend->buffer(); +} + +OverlayWindow *SceneXrender::overlayWindow() const +{ + return m_backend->overlayWindow(); +} + +bool SceneXrender::usesOverlayWindow() const +{ + return m_backend->usesOverlayWindow(); +} + //**************************************** // XRenderWindowPixmap //**************************************** diff --git a/plugins/scenes/xrender/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h index d90f487e73..0f31f46961 100644 --- a/plugins/scenes/xrender/scene_xrender.h +++ b/plugins/scenes/xrender/scene_xrender.h @@ -19,118 +19,7 @@ namespace KWin { -namespace Xcb -{ - class Shm; -} - -/** - * @brief Backend for the SceneXRender to hold the compositing buffer and take care of buffer - * swapping. - * - * This class is intended as a small abstraction to support multiple compositing backends in the - * SceneXRender. - */ -class XRenderBackend -{ -public: - virtual ~XRenderBackend(); - virtual void present(int mask, const QRegion &damage) = 0; - - /** - * @brief Returns the OverlayWindow used by the backend. - * - * A backend does not have to use an OverlayWindow, this is mostly for the X world. - * In case the backend does not use an OverlayWindow it is allowed to return @c null. - * It's the task of the caller to check whether it is @c null. - * - * @return :OverlayWindow* - */ - virtual OverlayWindow *overlayWindow(); - virtual bool usesOverlayWindow() const = 0; - /** - * @brief Shows the Overlay Window - * - * Default implementation does nothing. - */ - virtual void showOverlay(); - /** - * @brief React on screen geometry changes. - * - * Default implementation does nothing. Override if specific functionality is required. - * - * @param size The new screen size - */ - virtual void screenGeometryChanged(const QSize &size); - /** - * @brief The compositing buffer hold by this backend. - * - * The Scene composites the new frame into this buffer. - * - * @return xcb_render_picture_t - */ - xcb_render_picture_t buffer() const { - return m_buffer; - } - /** - * @brief Whether the creation of the Backend failed. - * - * The SceneXRender should test whether the Backend got constructed correctly. If this method - * returns @c true, the SceneXRender should not try to start the rendering. - * - * @return bool @c true if the creation of the Backend failed, @c false otherwise. - */ - bool isFailed() const { - return m_failed; - } - -protected: - XRenderBackend(); - /** - * @brief A subclass needs to call this method once it created the compositing back buffer. - * - * @param buffer The buffer to use for compositing - * @return void - */ - void setBuffer(xcb_render_picture_t buffer); - /** - * @brief Sets the backend initialization to failed. - * - * This method should be called by the concrete subclass in case the initialization failed. - * The given @p reason is logged as a warning. - * - * @param reason The reason why the initialization failed. - */ - void setFailed(const QString &reason); - -private: - // Create the compositing buffer. The root window is not double-buffered, - // so it is done manually using this buffer, - xcb_render_picture_t m_buffer; - bool m_failed; -}; - -/** - * @brief XRenderBackend using an X11 Overlay Window as compositing target. - */ -class X11XRenderBackend : public XRenderBackend -{ -public: - X11XRenderBackend(); - ~X11XRenderBackend() override; - - void present(int mask, const QRegion &damage) override; - OverlayWindow* overlayWindow() override; - void showOverlay() override; - void screenGeometryChanged(const QSize &size) override; - bool usesOverlayWindow() const override; -private: - void init(bool createOverlay); - void createBuffer(); - QScopedPointer m_overlayWindow; - xcb_render_picture_t m_front; - xcb_render_pictformat_t m_format; -}; +class XRenderBackend; class SceneXrender : public Scene @@ -148,12 +37,8 @@ public: Shadow *createShadow(Toplevel *toplevel) override; void screenGeometryChanged(const QSize &size) override; xcb_render_picture_t xrenderBufferPicture() const override; - OverlayWindow *overlayWindow() const override { - return m_backend->overlayWindow(); - } - bool usesOverlayWindow() const override { - return m_backend->usesOverlayWindow(); - } + OverlayWindow *overlayWindow() const override; + bool usesOverlayWindow() const override; Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *client) override; bool animationsSupported() const override { @@ -243,12 +128,6 @@ private: static XRenderPicture* s_effectFrameCircle; }; -inline -xcb_render_picture_t SceneXrender::xrenderBufferPicture() const -{ - return m_backend->buffer(); -} - inline QRegion SceneXrender::Window::transformedShape() const {