From a2c91f943400f644d26386dad41826b074d3cf56 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Tue, 26 Apr 2022 11:53:01 +0200 Subject: [PATCH] backends/x11: Cleanup KWinXRenderUtils and move it to eglx11common The XRender backend has been removed, leaving most of KWinXRenderUtils unused. The few features that are still used, notable `XRenderPicture` and pict format are moved into the x11/common directory. Signed-off-by: Victoria Fischer --- autotests/CMakeLists.txt | 1 - autotests/libxrenderutils/CMakeLists.txt | 17 -- .../libxrenderutils/blendpicture_test.cpp | 55 ---- src/backends/x11/common/CMakeLists.txt | 6 +- src/backends/x11/common/kwinxrenderutils.cpp | 149 +++++++++ src/backends/x11/common/kwinxrenderutils.h | 102 +++++++ src/backends/x11/common/logging.cpp | 10 + src/backends/x11/common/logging_p.h | 17 ++ src/backends/x11/standalone/CMakeLists.txt | 2 +- src/backends/x11/standalone/x11_platform.cpp | 6 - src/backends/x11/windowed/CMakeLists.txt | 2 +- .../x11/windowed/x11windowed_backend.cpp | 1 - src/libkwineffects/CMakeLists.txt | 28 -- src/libkwineffects/kwinxrenderutils.cpp | 287 ------------------ src/libkwineffects/kwinxrenderutils.h | 181 ----------- src/libkwineffects/logging.cpp | 1 - src/libkwineffects/logging_p.h | 1 - 17 files changed, 285 insertions(+), 581 deletions(-) delete mode 100644 autotests/libxrenderutils/CMakeLists.txt delete mode 100644 autotests/libxrenderutils/blendpicture_test.cpp create mode 100644 src/backends/x11/common/kwinxrenderutils.cpp create mode 100644 src/backends/x11/common/kwinxrenderutils.h create mode 100644 src/backends/x11/common/logging.cpp create mode 100644 src/backends/x11/common/logging_p.h delete mode 100644 src/libkwineffects/kwinxrenderutils.cpp delete mode 100644 src/libkwineffects/kwinxrenderutils.h diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 31d1e227b4..6735ea79af 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,7 +1,6 @@ add_definitions(-DKWIN_UNIT_TEST) remove_definitions(-DQT_USE_QSTRINGBUILDER) add_subdirectory(libkwineffects) -add_subdirectory(libxrenderutils) add_subdirectory(integration) add_subdirectory(libinput) add_subdirectory(tabbox) diff --git a/autotests/libxrenderutils/CMakeLists.txt b/autotests/libxrenderutils/CMakeLists.txt deleted file mode 100644 index 2fb9860846..0000000000 --- a/autotests/libxrenderutils/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_executable(blendPictureTest blendpicture_test.cpp) -set_target_properties(blendPictureTest PROPERTIES COMPILE_DEFINITIONS "NO_NONE_WINDOW") -add_test(NAME xrenderutils-blendPictureTest COMMAND blendPictureTest) -target_link_libraries(blendPictureTest - kwinxrenderutils - Qt::Test - Qt::Gui - XCB::XCB - XCB::RENDER - XCB::XFIXES -) -if (QT_MAJOR_VERSION EQUAL "5") - target_link_libraries(blendPictureTest Qt::X11Extras) -else() - target_link_libraries(blendPictureTest Qt::GuiPrivate) -endif() -ecm_mark_as_test(blendPictureTest) diff --git a/autotests/libxrenderutils/blendpicture_test.cpp b/autotests/libxrenderutils/blendpicture_test.cpp deleted file mode 100644 index b2d84d00d9..0000000000 --- a/autotests/libxrenderutils/blendpicture_test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2016 Martin Gräßlin - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#include -#include -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) -#include -#else -#include -#endif - -#include "../testutils.h" - -#include "kwinxrenderutils.h" - -class BlendPictureTest : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void initTestCase(); - void cleanupTestCase(); - - void testDontCrashOnTeardown(); -}; - -void BlendPictureTest::initTestCase() -{ - KWin::XRenderUtils::init(QX11Info::connection(), QX11Info::appRootWindow()); -} - -void BlendPictureTest::cleanupTestCase() -{ - KWin::XRenderUtils::cleanup(); -} - -void BlendPictureTest::testDontCrashOnTeardown() -{ - // this test uses xrenderBlendPicture - the only idea is to trigger the creation - // closing the application should not crash - // see BUG 363251 - const auto picture = KWin::xRenderBlendPicture(0.5); - // and a second one - const auto picture2 = KWin::xRenderBlendPicture(0.6); - Q_UNUSED(picture) - Q_UNUSED(picture2) -} - -Q_CONSTRUCTOR_FUNCTION(forceXcb) -QTEST_MAIN(BlendPictureTest) -#include "blendpicture_test.moc" diff --git a/src/backends/x11/common/CMakeLists.txt b/src/backends/x11/common/CMakeLists.txt index 20622d2d07..2b0c4d43d8 100644 --- a/src/backends/x11/common/CMakeLists.txt +++ b/src/backends/x11/common/CMakeLists.txt @@ -4,5 +4,9 @@ endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-int-to-void-pointer-cast") endif() -add_library(eglx11common STATIC eglonxbackend.cpp) +add_library(eglx11common STATIC + eglonxbackend.cpp + kwinxrenderutils.cpp + logging.cpp +) target_link_libraries(eglx11common kwin) diff --git a/src/backends/x11/common/kwinxrenderutils.cpp b/src/backends/x11/common/kwinxrenderutils.cpp new file mode 100644 index 0000000000..6dd533a9f1 --- /dev/null +++ b/src/backends/x11/common/kwinxrenderutils.cpp @@ -0,0 +1,149 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2008 Lubos Lunak + SPDX-FileCopyrightText: 2022 MBition GmbH + SPDX-FileContributor: Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "kwinxrenderutils.h" +#include "logging_p.h" +#include "main.h" + +#include +#include + +namespace KWin +{ + +static xcb_render_picture_t createPicture(xcb_pixmap_t pix, int depth) +{ + if (pix == XCB_PIXMAP_NONE) { + return XCB_RENDER_PICTURE_NONE; + } + xcb_connection_t *c = kwinApp()->x11Connection(); + static QHash s_renderFormats; + if (!s_renderFormats.contains(depth)) { + xcb_render_query_pict_formats_reply_t *formats = xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats_unchecked(c), nullptr); + if (!formats) { + return XCB_RENDER_PICTURE_NONE; + } + for (xcb_render_pictforminfo_iterator_t it = xcb_render_query_pict_formats_formats_iterator(formats); + it.rem; + xcb_render_pictforminfo_next(&it)) { + if (it.data->depth == depth) { + s_renderFormats.insert(depth, it.data->id); + break; + } + } + free(formats); + } + QHash::const_iterator it = s_renderFormats.constFind(depth); + if (it == s_renderFormats.constEnd()) { + qCWarning(LIBKWINXRENDERUTILS) << "Could not find XRender format for depth" << depth; + return XCB_RENDER_PICTURE_NONE; + } + xcb_render_picture_t pic = xcb_generate_id(c); + xcb_render_create_picture(c, pic, pix, it.value(), 0, nullptr); + return pic; +} + +XRenderPicture::XRenderPicture(const QImage &img) +{ + fromImage(img); +} + +void XRenderPicture::fromImage(const QImage &img) +{ + xcb_connection_t *c = kwinApp()->x11Connection(); + const int depth = img.depth(); + xcb_pixmap_t xpix = xcb_generate_id(c); + xcb_create_pixmap(c, depth, xpix, kwinApp()->x11RootWindow(), img.width(), img.height()); + + xcb_gcontext_t cid = xcb_generate_id(c); + xcb_create_gc(c, cid, xpix, 0, nullptr); + xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, xpix, cid, img.width(), img.height(), + 0, 0, 0, depth, img.sizeInBytes(), img.constBits()); + xcb_free_gc(c, cid); + + d = new XRenderPictureData(createPicture(xpix, depth)); + xcb_free_pixmap(c, xpix); +} + +XRenderPicture::XRenderPicture(xcb_pixmap_t pix, int depth) + : d(new XRenderPictureData(createPicture(pix, depth))) +{ +} + +XRenderPictureData::~XRenderPictureData() +{ + if (picture != XCB_RENDER_PICTURE_NONE) { + Q_ASSERT(qApp); + xcb_render_free_picture(kwinApp()->x11Connection(), picture); + } +} + +namespace XRenderUtils +{ + +struct PictFormatData +{ + PictFormatData() + { + // Fetch the render pict formats + reply = xcb_render_query_pict_formats_reply(kwinApp()->x11Connection(), + xcb_render_query_pict_formats_unchecked(kwinApp()->x11Connection()), nullptr); + + // Init the visual ID -> format ID hash table + for (auto screens = xcb_render_query_pict_formats_screens_iterator(reply); screens.rem; xcb_render_pictscreen_next(&screens)) { + for (auto depths = xcb_render_pictscreen_depths_iterator(screens.data); depths.rem; xcb_render_pictdepth_next(&depths)) { + const xcb_render_pictvisual_t *visuals = xcb_render_pictdepth_visuals(depths.data); + const int len = xcb_render_pictdepth_visuals_length(depths.data); + + for (int i = 0; i < len; i++) { + visualHash.insert(visuals[i].visual, visuals[i].format); + } + } + } + + // Init the format ID -> xcb_render_directformat_t* hash table + const xcb_render_pictforminfo_t *formats = xcb_render_query_pict_formats_formats(reply); + const int len = xcb_render_query_pict_formats_formats_length(reply); + + for (int i = 0; i < len; i++) { + if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT) { + formatInfoHash.insert(formats[i].id, &formats[i].direct); + } + } + } + + ~PictFormatData() + { + free(reply); + } + + xcb_render_query_pict_formats_reply_t *reply; + QHash visualHash; + QHash formatInfoHash; +}; + +Q_GLOBAL_STATIC(PictFormatData, g_pictFormatData) + +xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual) +{ + PictFormatData *d = g_pictFormatData; + return d->visualHash.value(visual); +} + +const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format) +{ + PictFormatData *d = g_pictFormatData; + return d->formatInfoHash.value(format); +} + +} // namespace XRenderUtils + +} // namespace KWin diff --git a/src/backends/x11/common/kwinxrenderutils.h b/src/backends/x11/common/kwinxrenderutils.h new file mode 100644 index 0000000000..258586f55f --- /dev/null +++ b/src/backends/x11/common/kwinxrenderutils.h @@ -0,0 +1,102 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2008 Lubos Lunak + SPDX-FileCopyrightText: 2022 MBition GmbH + SPDX-FileContributor: Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#ifndef KWIN_XRENDERUTILS_H +#define KWIN_XRENDERUTILS_H + +// KWin +#include +// Qt +#include +// XCB +#include + +class QImage; + +/** @addtogroup kwineffects */ +/** @{ */ + +namespace KWin +{ + +/** @internal */ +class KWIN_EXPORT XRenderPictureData + : public QSharedData +{ +public: + explicit XRenderPictureData(xcb_render_picture_t pic = XCB_RENDER_PICTURE_NONE); + ~XRenderPictureData(); + xcb_render_picture_t value(); + +private: + xcb_render_picture_t picture; + Q_DISABLE_COPY(XRenderPictureData) +}; + +/** + * @short Wrapper around XRender Picture. + * + * This class wraps XRender's Picture, providing proper initialization, + * convenience constructors and freeing of resources. + * It should otherwise act exactly like the Picture type. + */ +class KWIN_EXPORT XRenderPicture +{ +public: + explicit XRenderPicture(xcb_render_picture_t pic = XCB_RENDER_PICTURE_NONE); + explicit XRenderPicture(const QImage &img); + XRenderPicture(xcb_pixmap_t pix, int depth); + operator xcb_render_picture_t(); + +private: + void fromImage(const QImage &img); + QExplicitlySharedDataPointer d; +}; + +inline XRenderPictureData::XRenderPictureData(xcb_render_picture_t pic) + : picture(pic) +{ +} + +inline xcb_render_picture_t XRenderPictureData::value() +{ + return picture; +} + +inline XRenderPicture::XRenderPicture(xcb_render_picture_t pic) + : d(new XRenderPictureData(pic)) +{ +} + +inline XRenderPicture::operator xcb_render_picture_t() +{ + return d->value(); +} + +namespace XRenderUtils +{ +/** + * Returns the Xrender format that corresponds to the given visual ID. + */ +KWIN_EXPORT xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual); + +/** + * Returns the xcb_render_directformat_t for the given Xrender format. + */ +KWIN_EXPORT const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format); + +} // namespace XRenderUtils + +} // namespace KWin + +/** @} */ + +#endif diff --git a/src/backends/x11/common/logging.cpp b/src/backends/x11/common/logging.cpp new file mode 100644 index 0000000000..75d6f32433 --- /dev/null +++ b/src/backends/x11/common/logging.cpp @@ -0,0 +1,10 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2015 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#include "logging_p.h" +Q_LOGGING_CATEGORY(LIBKWINXRENDERUTILS, "libkwinxrenderutils", QtWarningMsg) diff --git a/src/backends/x11/common/logging_p.h b/src/backends/x11/common/logging_p.h new file mode 100644 index 0000000000..161033d208 --- /dev/null +++ b/src/backends/x11/common/logging_p.h @@ -0,0 +1,17 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2015 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#ifndef KWIN_KWINXRENDERUTILS_LOGGING_P_H +#define KWIN_KWINXRENDERUTILS_LOGGING_P_H + +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(LIBKWINXRENDERUTILS) + +#endif diff --git a/src/backends/x11/standalone/CMakeLists.txt b/src/backends/x11/standalone/CMakeLists.txt index cca1c682d2..0c72c319d1 100644 --- a/src/backends/x11/standalone/CMakeLists.txt +++ b/src/backends/x11/standalone/CMakeLists.txt @@ -17,7 +17,7 @@ set(X11PLATFORM_SOURCES 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 KF5::Crash X11::X11) +target_link_libraries(KWinX11Platform eglx11common kwin KF5::Crash X11::X11) if (QT_MAJOR_VERSION EQUAL "5") target_link_libraries(KWinX11Platform Qt::X11Extras) endif() diff --git a/src/backends/x11/standalone/x11_platform.cpp b/src/backends/x11/standalone/x11_platform.cpp index 74c59cef08..9a26c3cf29 100644 --- a/src/backends/x11/standalone/x11_platform.cpp +++ b/src/backends/x11/standalone/x11_platform.cpp @@ -36,8 +36,6 @@ #include "workspace.h" #include "x11_output.h" -#include - #include #include #include @@ -131,9 +129,6 @@ X11StandalonePlatform::~X11StandalonePlatform() if (sceneEglDisplay() != EGL_NO_DISPLAY) { eglTerminate(sceneEglDisplay()); } - if (isReady()) { - XRenderUtils::cleanup(); - } } bool X11StandalonePlatform::initialize() @@ -141,7 +136,6 @@ bool X11StandalonePlatform::initialize() if (!QX11Info::isPlatformX11()) { return false; } - XRenderUtils::init(kwinApp()->x11Connection(), kwinApp()->x11RootWindow()); setReady(true); initOutputs(); diff --git a/src/backends/x11/windowed/CMakeLists.txt b/src/backends/x11/windowed/CMakeLists.txt index 641890a0e1..9cb4f08b25 100644 --- a/src/backends/x11/windowed/CMakeLists.txt +++ b/src/backends/x11/windowed/CMakeLists.txt @@ -8,7 +8,7 @@ set(X11BACKEND_SOURCES add_library(KWinWaylandX11Backend MODULE ${X11BACKEND_SOURCES}) set_target_properties(KWinWaylandX11Backend PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/org.kde.kwin.waylandbackends/") -target_link_libraries(KWinWaylandX11Backend eglx11common kwin kwinxrenderutils X11::XCB X11::X11) +target_link_libraries(KWinWaylandX11Backend eglx11common kwin X11::XCB X11::X11) if (X11_Xi_FOUND) target_link_libraries(KWinWaylandX11Backend X11::Xi) endif() diff --git a/src/backends/x11/windowed/x11windowed_backend.cpp b/src/backends/x11/windowed/x11windowed_backend.cpp index fd86731c41..612c52db93 100644 --- a/src/backends/x11/windowed/x11windowed_backend.cpp +++ b/src/backends/x11/windowed/x11windowed_backend.cpp @@ -210,7 +210,6 @@ bool X11WindowedBackend::initialize() } } initXInput(); - XRenderUtils::init(m_connection, m_screen->root); createOutputs(); connect(kwinApp(), &Application::workspaceCreated, this, &X11WindowedBackend::startEventReading); connect(Cursors::self(), &Cursors::currentCursorChanged, this, [this]() { diff --git a/src/libkwineffects/CMakeLists.txt b/src/libkwineffects/CMakeLists.txt index 30d81e8f43..cc1c7ffcb1 100644 --- a/src/libkwineffects/CMakeLists.txt +++ b/src/libkwineffects/CMakeLists.txt @@ -8,32 +8,6 @@ ecm_setup_version(${PROJECT_VERSION} SOVERSION 13 ) -### xrenderutils lib ### -set(kwin_XRENDERUTILS_SRCS - kwinxrenderutils.cpp - logging.cpp -) - -add_library(kwinxrenderutils SHARED ${kwin_XRENDERUTILS_SRCS}) -generate_export_header(kwinxrenderutils EXPORT_FILE_NAME kwinxrenderutils_export.h) -target_link_libraries(kwinxrenderutils - PUBLIC - Qt::Core - Qt::Gui - - XCB::RENDER - XCB::XCB - XCB::XFIXES -) - -set_target_properties(kwinxrenderutils PROPERTIES - VERSION ${KWINEFFECTS_VERSION} - SOVERSION ${KWINEFFECTS_SOVERSION} -) -set_target_properties(kwinxrenderutils PROPERTIES OUTPUT_NAME ${KWIN_NAME}xrenderutils) - -install(TARGETS kwinxrenderutils EXPORT KWinEffectsTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) - ### effects lib ### set(kwin_EFFECTSLIB_SRCS anidata.cpp @@ -95,7 +69,6 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kwinconfig.h ${CMAKE_CURRENT_BINARY_DIR}/kwineffects_export.h ${CMAKE_CURRENT_BINARY_DIR}/kwinglutils_export.h - ${CMAKE_CURRENT_BINARY_DIR}/kwinxrenderutils_export.h kwinanimationeffect.h kwindeformeffect.h kwineffects.h @@ -106,7 +79,6 @@ install(FILES kwinglutils_funcs.h kwinoffscreenquickview.h kwinquickeffect.h - kwinxrenderutils.h DESTINATION ${KDE_INSTALL_INCLUDEDIR} COMPONENT Devel) set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KWinEffects") diff --git a/src/libkwineffects/kwinxrenderutils.cpp b/src/libkwineffects/kwinxrenderutils.cpp deleted file mode 100644 index 375c7a686e..0000000000 --- a/src/libkwineffects/kwinxrenderutils.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2008 Lubos Lunak - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#include "kwinxrenderutils.h" -#include "logging_p.h" - -#include -#include -#include -#include - -namespace KWin -{ - -namespace XRenderUtils -{ -static xcb_connection_t *s_connection = nullptr; -static xcb_window_t s_rootWindow = XCB_WINDOW_NONE; -static XRenderPicture s_blendPicture(XCB_RENDER_PICTURE_NONE); - -void init(xcb_connection_t *connection, xcb_window_t rootWindow) -{ - s_connection = connection; - s_rootWindow = rootWindow; -} - -void cleanup() -{ - s_blendPicture = XRenderPicture(XCB_RENDER_PICTURE_NONE); - s_connection = nullptr; - s_rootWindow = XCB_WINDOW_NONE; -} - -} // namespace - -// adapted from Qt, because this really sucks ;) -xcb_render_color_t preMultiply(const QColor &c, float opacity) -{ - xcb_render_color_t color; - const uint A = c.alpha() * opacity, - R = c.red(), - G = c.green(), - B = c.blue(); - color.alpha = (A | A << 8); - color.red = (R | R << 8) * color.alpha / 0x10000; - color.green = (G | G << 8) * color.alpha / 0x10000; - color.blue = (B | B << 8) * color.alpha / 0x10000; - return color; -} - -XRenderPicture xRenderFill(const xcb_render_color_t &c) -{ - xcb_pixmap_t pixmap = xcb_generate_id(XRenderUtils::s_connection); - xcb_create_pixmap(XRenderUtils::s_connection, 32, pixmap, XRenderUtils::s_rootWindow, 1, 1); - XRenderPicture fill(pixmap, 32); - xcb_free_pixmap(XRenderUtils::s_connection, pixmap); - - uint32_t values[] = {true}; - xcb_render_change_picture(XRenderUtils::s_connection, fill, XCB_RENDER_CP_REPEAT, values); - - xcb_rectangle_t rect = {0, 0, 1, 1}; - xcb_render_fill_rectangles(XRenderUtils::s_connection, XCB_RENDER_PICT_OP_SRC, fill, c, 1, &rect); - return fill; -} - -XRenderPicture xRenderFill(const QColor &c) -{ - return xRenderFill(preMultiply(c)); -} - -XRenderPicture xRenderBlendPicture(double opacity) -{ - static xcb_render_color_t s_blendColor = {0, 0, 0, 0}; - s_blendColor.alpha = uint16_t(opacity * 0xffff); - if (XRenderUtils::s_blendPicture == XCB_RENDER_PICTURE_NONE) { - XRenderUtils::s_blendPicture = xRenderFill(s_blendColor); - } else { - xcb_rectangle_t rect = {0, 0, 1, 1}; - xcb_render_fill_rectangles(XRenderUtils::s_connection, XCB_RENDER_PICT_OP_SRC, XRenderUtils::s_blendPicture, s_blendColor, 1, &rect); - } - return XRenderUtils::s_blendPicture; -} - -static xcb_render_picture_t createPicture(xcb_pixmap_t pix, int depth) -{ - if (pix == XCB_PIXMAP_NONE) { - return XCB_RENDER_PICTURE_NONE; - } - xcb_connection_t *c = XRenderUtils::s_connection; - static QHash s_renderFormats; - if (!s_renderFormats.contains(depth)) { - xcb_render_query_pict_formats_reply_t *formats = xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats_unchecked(c), nullptr); - if (!formats) { - return XCB_RENDER_PICTURE_NONE; - } - for (xcb_render_pictforminfo_iterator_t it = xcb_render_query_pict_formats_formats_iterator(formats); - it.rem; - xcb_render_pictforminfo_next(&it)) { - if (it.data->depth == depth) { - s_renderFormats.insert(depth, it.data->id); - break; - } - } - free(formats); - } - QHash::const_iterator it = s_renderFormats.constFind(depth); - if (it == s_renderFormats.constEnd()) { - qCWarning(LIBKWINXRENDERUTILS) << "Could not find XRender format for depth" << depth; - return XCB_RENDER_PICTURE_NONE; - } - xcb_render_picture_t pic = xcb_generate_id(c); - xcb_render_create_picture(c, pic, pix, it.value(), 0, nullptr); - return pic; -} - -XRenderPicture::XRenderPicture(const QImage &img) -{ - fromImage(img); -} - -void XRenderPicture::fromImage(const QImage &img) -{ - xcb_connection_t *c = XRenderUtils::s_connection; - const int depth = img.depth(); - xcb_pixmap_t xpix = xcb_generate_id(c); - xcb_create_pixmap(c, depth, xpix, XRenderUtils::s_rootWindow, img.width(), img.height()); - - xcb_gcontext_t cid = xcb_generate_id(c); - xcb_create_gc(c, cid, xpix, 0, nullptr); - xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, xpix, cid, img.width(), img.height(), - 0, 0, 0, depth, img.sizeInBytes(), img.constBits()); - xcb_free_gc(c, cid); - - d = new XRenderPictureData(createPicture(xpix, depth)); - xcb_free_pixmap(c, xpix); -} - -XRenderPicture::XRenderPicture(xcb_pixmap_t pix, int depth) - : d(new XRenderPictureData(createPicture(pix, depth))) -{ -} - -XRenderPictureData::~XRenderPictureData() -{ - if (picture != XCB_RENDER_PICTURE_NONE) { - Q_ASSERT(qApp); - xcb_render_free_picture(XRenderUtils::s_connection, picture); - } -} - -XFixesRegion::XFixesRegion(const QRegion ®ion) -{ - m_region = xcb_generate_id(XRenderUtils::s_connection); - QVector xrects; - xrects.reserve(region.rectCount()); - for (const QRect &rect : region) { - xcb_rectangle_t xrect; - xrect.x = rect.x(); - xrect.y = rect.y(); - xrect.width = rect.width(); - xrect.height = rect.height(); - xrects.append(xrect); - } - xcb_xfixes_create_region(XRenderUtils::s_connection, m_region, xrects.count(), xrects.constData()); -} - -XFixesRegion::~XFixesRegion() -{ - xcb_xfixes_destroy_region(XRenderUtils::s_connection, m_region); -} - -static xcb_render_picture_t s_offscreenTarget = XCB_RENDER_PICTURE_NONE; -static QStack s_scene_offscreenTargetStack; -static int s_renderOffscreen = 0; - -void scene_setXRenderOffscreenTarget(xcb_render_picture_t pix) -{ - s_offscreenTarget = pix; -} - -XRenderPicture *scene_xRenderOffscreenTarget() -{ - return s_scene_offscreenTargetStack.isEmpty() ? nullptr : s_scene_offscreenTargetStack.top(); -} - -void setXRenderOffscreen(bool b) -{ - b ? ++s_renderOffscreen : --s_renderOffscreen; - if (s_renderOffscreen < 0) { - s_renderOffscreen = 0; - qCWarning(LIBKWINXRENDERUTILS) << "*** SOMETHING IS MESSED UP WITH YOUR setXRenderOffscreen() USAGE ***"; - } -} - -void xRenderPushTarget(XRenderPicture *pic) -{ - s_scene_offscreenTargetStack.push(pic); - ++s_renderOffscreen; -} - -void xRenderPopTarget() -{ - s_scene_offscreenTargetStack.pop(); - --s_renderOffscreen; - if (s_renderOffscreen < 0) { - s_renderOffscreen = 0; - qCWarning(LIBKWINXRENDERUTILS) << "*** SOMETHING IS MESSED UP WITH YOUR xRenderPopTarget() USAGE ***"; - } -} - -bool xRenderOffscreen() -{ - return s_renderOffscreen; -} - -xcb_render_picture_t xRenderOffscreenTarget() -{ - return s_offscreenTarget; -} - -namespace XRenderUtils -{ - -struct PictFormatData -{ - PictFormatData() - { - // Fetch the render pict formats - reply = xcb_render_query_pict_formats_reply(s_connection, - xcb_render_query_pict_formats_unchecked(s_connection), nullptr); - - // Init the visual ID -> format ID hash table - for (auto screens = xcb_render_query_pict_formats_screens_iterator(reply); screens.rem; xcb_render_pictscreen_next(&screens)) { - for (auto depths = xcb_render_pictscreen_depths_iterator(screens.data); depths.rem; xcb_render_pictdepth_next(&depths)) { - const xcb_render_pictvisual_t *visuals = xcb_render_pictdepth_visuals(depths.data); - const int len = xcb_render_pictdepth_visuals_length(depths.data); - - for (int i = 0; i < len; i++) { - visualHash.insert(visuals[i].visual, visuals[i].format); - } - } - } - - // Init the format ID -> xcb_render_directformat_t* hash table - const xcb_render_pictforminfo_t *formats = xcb_render_query_pict_formats_formats(reply); - const int len = xcb_render_query_pict_formats_formats_length(reply); - - for (int i = 0; i < len; i++) { - if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT) { - formatInfoHash.insert(formats[i].id, &formats[i].direct); - } - } - } - - ~PictFormatData() - { - free(reply); - } - - xcb_render_query_pict_formats_reply_t *reply; - QHash visualHash; - QHash formatInfoHash; -}; - -Q_GLOBAL_STATIC(PictFormatData, g_pictFormatData) - -xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual) -{ - PictFormatData *d = g_pictFormatData; - return d->visualHash.value(visual); -} - -const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format) -{ - PictFormatData *d = g_pictFormatData; - return d->formatInfoHash.value(format); -} - -} // namespace XRenderUtils - -} // namespace KWin diff --git a/src/libkwineffects/kwinxrenderutils.h b/src/libkwineffects/kwinxrenderutils.h deleted file mode 100644 index a4b888ac03..0000000000 --- a/src/libkwineffects/kwinxrenderutils.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2008 Lubos Lunak - - SPDX-License-Identifier: GPL-2.0-or-later -*/ - -#ifndef KWIN_XRENDERUTILS_H -#define KWIN_XRENDERUTILS_H - -// KWin -#include -// Qt -#include -#include -#include -// XCB -#include - -class QColor; -class QPixmap; - -/** @addtogroup kwineffects */ -/** @{ */ - -namespace KWin -{ -/** - * dumps a QColor into a xcb_render_color_t - */ -KWINXRENDERUTILS_EXPORT xcb_render_color_t preMultiply(const QColor &c, float opacity = 1.0); - -/** @internal */ -class KWINXRENDERUTILS_EXPORT XRenderPictureData - : public QSharedData -{ -public: - explicit XRenderPictureData(xcb_render_picture_t pic = XCB_RENDER_PICTURE_NONE); - ~XRenderPictureData(); - xcb_render_picture_t value(); - -private: - xcb_render_picture_t picture; - Q_DISABLE_COPY(XRenderPictureData) -}; - -/** - * @short Wrapper around XRender Picture. - * - * This class wraps XRender's Picture, providing proper initialization, - * convenience constructors and freeing of resources. - * It should otherwise act exactly like the Picture type. - */ -class KWINXRENDERUTILS_EXPORT XRenderPicture -{ -public: - explicit XRenderPicture(xcb_render_picture_t pic = XCB_RENDER_PICTURE_NONE); - explicit XRenderPicture(const QImage &img); - XRenderPicture(xcb_pixmap_t pix, int depth); - operator xcb_render_picture_t(); - -private: - void fromImage(const QImage &img); - QExplicitlySharedDataPointer d; -}; - -class KWINXRENDERUTILS_EXPORT XFixesRegion -{ -public: - explicit XFixesRegion(const QRegion ®ion); - virtual ~XFixesRegion(); - - operator xcb_xfixes_region_t(); - -private: - xcb_xfixes_region_t m_region; -}; - -inline XRenderPictureData::XRenderPictureData(xcb_render_picture_t pic) - : picture(pic) -{ -} - -inline xcb_render_picture_t XRenderPictureData::value() -{ - return picture; -} - -inline XRenderPicture::XRenderPicture(xcb_render_picture_t pic) - : d(new XRenderPictureData(pic)) -{ -} - -inline XRenderPicture::operator xcb_render_picture_t() -{ - return d->value(); -} - -inline XFixesRegion::operator xcb_xfixes_region_t() -{ - return m_region; -} - -/** - * Static 1x1 picture used to deliver a black pixel with given opacity (for blending performance) - * Call and Use, the PixelPicture will stay, but may change it's opacity meanwhile. It's NOT threadsafe either - */ -KWINXRENDERUTILS_EXPORT XRenderPicture xRenderBlendPicture(double opacity); -/** - * Creates a 1x1 Picture filled with c - */ -KWINXRENDERUTILS_EXPORT XRenderPicture xRenderFill(const xcb_render_color_t &c); -KWINXRENDERUTILS_EXPORT XRenderPicture xRenderFill(const QColor &c); - -/** - * Allows to render a window into a (transparent) pixmap - * NOTICE: the result can be queried as xRenderWindowOffscreenTarget() - * NOTICE: it may be 0 - * NOTICE: when done call setXRenderWindowOffscreen(false) to continue normal render process - */ -KWINXRENDERUTILS_EXPORT void setXRenderOffscreen(bool b); - -/** - * Allows to define a persistent effect member as render target - * The window (including shadows) is rendered into the top left corner - * NOTICE: do NOT call setXRenderOffscreen(true) in addition! - * NOTICE: do not forget to xRenderPopTarget once you're done to continue the normal render process - */ -KWINXRENDERUTILS_EXPORT void xRenderPushTarget(XRenderPicture *pic); -KWINXRENDERUTILS_EXPORT void xRenderPopTarget(); - -/** - * Whether windows are currently rendered into an offscreen target buffer - */ -KWINXRENDERUTILS_EXPORT bool xRenderOffscreen(); -/** - * The offscreen buffer as set by the renderer because of setXRenderWindowOffscreen(true) - */ -KWINXRENDERUTILS_EXPORT xcb_render_picture_t xRenderOffscreenTarget(); - -/** - * NOTICE: HANDS OFF!!! - * scene_setXRenderWindowOffscreenTarget() is ONLY to be used by the renderer - DO NOT TOUCH! - */ -KWINXRENDERUTILS_EXPORT void scene_setXRenderOffscreenTarget(xcb_render_picture_t pix); -/** - * scene_xRenderWindowOffscreenTarget() is used by the scene to figure the target set by an effect - */ -KWINXRENDERUTILS_EXPORT XRenderPicture *scene_xRenderOffscreenTarget(); - -namespace XRenderUtils -{ -/** - * @internal - */ -KWINXRENDERUTILS_EXPORT void init(xcb_connection_t *connection, xcb_window_t rootWindow); - -/** - * Returns the Xrender format that corresponds to the given visual ID. - */ -KWINXRENDERUTILS_EXPORT xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual); - -/** - * Returns the xcb_render_directformat_t for the given Xrender format. - */ -KWINXRENDERUTILS_EXPORT const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format); - -/** - * @internal - */ -KWINXRENDERUTILS_EXPORT void cleanup(); - -} // namespace XRenderUtils - -} // namespace KWin - -/** @} */ - -#endif diff --git a/src/libkwineffects/logging.cpp b/src/libkwineffects/logging.cpp index eb7d5eabb2..5a80d98c49 100644 --- a/src/libkwineffects/logging.cpp +++ b/src/libkwineffects/logging.cpp @@ -9,4 +9,3 @@ #include "logging_p.h" Q_LOGGING_CATEGORY(LIBKWINEFFECTS, "libkwineffects", QtWarningMsg) Q_LOGGING_CATEGORY(LIBKWINGLUTILS, "libkwinglutils", QtWarningMsg) -Q_LOGGING_CATEGORY(LIBKWINXRENDERUTILS, "libkwinxrenderutils", QtWarningMsg) diff --git a/src/libkwineffects/logging_p.h b/src/libkwineffects/logging_p.h index d2a0665a6f..2410ea00a6 100644 --- a/src/libkwineffects/logging_p.h +++ b/src/libkwineffects/logging_p.h @@ -14,6 +14,5 @@ Q_DECLARE_LOGGING_CATEGORY(LIBKWINEFFECTS) Q_DECLARE_LOGGING_CATEGORY(LIBKWINGLUTILS) -Q_DECLARE_LOGGING_CATEGORY(LIBKWINXRENDERUTILS) #endif