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 <victoria.fischer@mbition.io>
This commit is contained in:
parent
3b46067fc1
commit
a2c91f9434
17 changed files with 285 additions and 581 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include <QLoggingCategory>
|
||||
#include <QtTest>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <private/qtx11extras_p.h>
|
||||
#else
|
||||
#include <QX11Info>
|
||||
#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"
|
|
@ -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)
|
||||
|
|
149
src/backends/x11/common/kwinxrenderutils.cpp
Normal file
149
src/backends/x11/common/kwinxrenderutils.cpp
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kwinxrenderutils.h"
|
||||
#include "logging_p.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QImage>
|
||||
|
||||
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<int, xcb_render_pictformat_t> 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<int, xcb_render_pictformat_t>::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<xcb_visualid_t, xcb_render_pictformat_t> visualHash;
|
||||
QHash<xcb_render_pictformat_t, const xcb_render_directformat_t *> 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
|
102
src/backends/x11/common/kwinxrenderutils.h
Normal file
102
src/backends/x11/common/kwinxrenderutils.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
|
||||
SPDX-FileCopyrightText: 2022 MBition GmbH
|
||||
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KWIN_XRENDERUTILS_H
|
||||
#define KWIN_XRENDERUTILS_H
|
||||
|
||||
// KWin
|
||||
#include <kwin_export.h>
|
||||
// Qt
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
// XCB
|
||||
#include <xcb/render.h>
|
||||
|
||||
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<XRenderPictureData> 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
|
10
src/backends/x11/common/logging.cpp
Normal file
10
src/backends/x11/common/logging.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include "logging_p.h"
|
||||
Q_LOGGING_CATEGORY(LIBKWINXRENDERUTILS, "libkwinxrenderutils", QtWarningMsg)
|
17
src/backends/x11/common/logging_p.h
Normal file
17
src/backends/x11/common/logging_p.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef KWIN_KWINXRENDERUTILS_LOGGING_P_H
|
||||
#define KWIN_KWINXRENDERUTILS_LOGGING_P_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(LIBKWINXRENDERUTILS)
|
||||
|
||||
#endif
|
|
@ -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()
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include "workspace.h"
|
||||
#include "x11_output.h"
|
||||
|
||||
#include <kwinxrenderutils.h>
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KCrash>
|
||||
#include <KGlobalAccel>
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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]() {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -1,287 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kwinxrenderutils.h"
|
||||
#include "logging_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QGlobalStatic>
|
||||
#include <QPixmap>
|
||||
#include <QStack>
|
||||
|
||||
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<int, xcb_render_pictformat_t> 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<int, xcb_render_pictformat_t>::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<xcb_rectangle_t> 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<XRenderPicture *> 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<xcb_visualid_t, xcb_render_pictformat_t> visualHash;
|
||||
QHash<xcb_render_pictformat_t, const xcb_render_directformat_t *> 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
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef KWIN_XRENDERUTILS_H
|
||||
#define KWIN_XRENDERUTILS_H
|
||||
|
||||
// KWin
|
||||
#include <kwinxrenderutils_export.h>
|
||||
// Qt
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
#include <QRegion>
|
||||
#include <QVector>
|
||||
// XCB
|
||||
#include <xcb/xfixes.h>
|
||||
|
||||
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<XRenderPictureData> 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
|
|
@ -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)
|
||||
|
|
|
@ -14,6 +14,5 @@
|
|||
|
||||
Q_DECLARE_LOGGING_CATEGORY(LIBKWINEFFECTS)
|
||||
Q_DECLARE_LOGGING_CATEGORY(LIBKWINGLUTILS)
|
||||
Q_DECLARE_LOGGING_CATEGORY(LIBKWINXRENDERUTILS)
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue