KWin
Loading...
Searching...
No Matches
kwinxrenderutils.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2008 Lubos Lunak <l.lunak@kde.org>
6 SPDX-FileCopyrightText: 2022 MBition GmbH
7 SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
8
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11
12#include "kwinxrenderutils.h"
14
15#include <QCoreApplication>
16#include <QImage>
17
18namespace KWin
19{
20
21namespace XRenderUtils
22{
23static xcb_connection_t *s_connection = nullptr;
24static xcb_window_t s_rootWindow = XCB_WINDOW_NONE;
25
26void init(xcb_connection_t *connection, xcb_window_t rootWindow)
27{
28 s_connection = connection;
29 s_rootWindow = rootWindow;
30}
31
32void cleanup()
33{
34 s_connection = nullptr;
35 s_rootWindow = XCB_WINDOW_NONE;
36}
37
38} // namespace
39
40static xcb_render_picture_t createPicture(xcb_pixmap_t pix, int depth)
41{
42 if (pix == XCB_PIXMAP_NONE) {
43 return XCB_RENDER_PICTURE_NONE;
44 }
45 xcb_connection_t *c = XRenderUtils::s_connection;
46 static QHash<int, xcb_render_pictformat_t> s_renderFormats;
47 if (!s_renderFormats.contains(depth)) {
48 xcb_render_query_pict_formats_reply_t *formats = xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats_unchecked(c), nullptr);
49 if (!formats) {
50 return XCB_RENDER_PICTURE_NONE;
51 }
52 for (xcb_render_pictforminfo_iterator_t it = xcb_render_query_pict_formats_formats_iterator(formats);
53 it.rem;
54 xcb_render_pictforminfo_next(&it)) {
55 if (it.data->depth == depth) {
56 s_renderFormats.insert(depth, it.data->id);
57 break;
58 }
59 }
60 free(formats);
61 }
62 QHash<int, xcb_render_pictformat_t>::const_iterator it = s_renderFormats.constFind(depth);
63 if (it == s_renderFormats.constEnd()) {
64 qCWarning(LIBKWINXRENDERUTILS) << "Could not find XRender format for depth" << depth;
65 return XCB_RENDER_PICTURE_NONE;
66 }
67 xcb_render_picture_t pic = xcb_generate_id(c);
68 xcb_render_create_picture(c, pic, pix, it.value(), 0, nullptr);
69 return pic;
70}
71
73{
74 fromImage(img);
75}
76
77void XRenderPicture::fromImage(const QImage &img)
78{
79 xcb_connection_t *c = XRenderUtils::s_connection;
80 const int depth = img.depth();
81 xcb_pixmap_t xpix = xcb_generate_id(c);
82 xcb_create_pixmap(c, depth, xpix, XRenderUtils::s_rootWindow, img.width(), img.height());
83
84 xcb_gcontext_t cid = xcb_generate_id(c);
85 xcb_create_gc(c, cid, xpix, 0, nullptr);
86 xcb_put_image(c, XCB_IMAGE_FORMAT_Z_PIXMAP, xpix, cid, img.width(), img.height(),
87 0, 0, 0, depth, img.sizeInBytes(), img.constBits());
88 xcb_free_gc(c, cid);
89
90 d = std::make_unique<XRenderPictureData>(createPicture(xpix, depth));
91 xcb_free_pixmap(c, xpix);
92}
93
94XRenderPicture::XRenderPicture(xcb_pixmap_t pix, int depth)
95 : d(std::make_unique<XRenderPictureData>(createPicture(pix, depth)))
96{
97}
98
100{
101 if (picture != XCB_RENDER_PICTURE_NONE) {
102 Q_ASSERT(qApp);
103 xcb_render_free_picture(XRenderUtils::s_connection, picture);
104 }
105}
106
107namespace XRenderUtils
108{
109
111{
113 {
114 // Fetch the render pict formats
115 reply = xcb_render_query_pict_formats_reply(s_connection,
116 xcb_render_query_pict_formats_unchecked(s_connection), nullptr);
117
118 // Init the visual ID -> format ID hash table
119 for (auto screens = xcb_render_query_pict_formats_screens_iterator(reply); screens.rem; xcb_render_pictscreen_next(&screens)) {
120 for (auto depths = xcb_render_pictscreen_depths_iterator(screens.data); depths.rem; xcb_render_pictdepth_next(&depths)) {
121 const xcb_render_pictvisual_t *visuals = xcb_render_pictdepth_visuals(depths.data);
122 const int len = xcb_render_pictdepth_visuals_length(depths.data);
123
124 for (int i = 0; i < len; i++) {
125 visualHash.insert(visuals[i].visual, visuals[i].format);
126 }
127 }
128 }
129
130 // Init the format ID -> xcb_render_directformat_t* hash table
131 const xcb_render_pictforminfo_t *formats = xcb_render_query_pict_formats_formats(reply);
132 const int len = xcb_render_query_pict_formats_formats_length(reply);
133
134 for (int i = 0; i < len; i++) {
135 if (formats[i].type == XCB_RENDER_PICT_TYPE_DIRECT) {
136 formatInfoHash.insert(formats[i].id, &formats[i].direct);
137 }
138 }
139 }
140
142 {
143 free(reply);
144 }
145
146 xcb_render_query_pict_formats_reply_t *reply;
147 QHash<xcb_visualid_t, xcb_render_pictformat_t> visualHash;
148 QHash<xcb_render_pictformat_t, const xcb_render_directformat_t *> formatInfoHash;
149};
150
151Q_GLOBAL_STATIC(PictFormatData, g_pictFormatData)
152
153xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual)
154{
155 PictFormatData *d = g_pictFormatData;
156 return d->visualHash.value(visual);
157}
158
159const xcb_render_directformat_t *findPictFormatInfo(xcb_render_pictformat_t format)
160{
161 PictFormatData *d = g_pictFormatData;
162 return d->formatInfoHash.value(format);
163}
164
165} // namespace XRenderUtils
166
167} // namespace KWin
XRenderPicture(xcb_render_picture_t pic=XCB_RENDER_PICTURE_NONE)
void init(xcb_connection_t *connection, xcb_window_t rootWindow)
const xcb_render_directformat_t * findPictFormatInfo(xcb_render_pictformat_t format)
xcb_render_pictformat_t findPictFormat(xcb_visualid_t visual)
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
Session::Type type
Definition session.cpp:17
GLenum format
Definition gltexture.cpp:49
KWIN_EXPORT xcb_connection_t * connection()
Definition xcb.h:19
QHash< xcb_render_pictformat_t, const xcb_render_directformat_t * > formatInfoHash
xcb_render_query_pict_formats_reply_t * reply
QHash< xcb_visualid_t, xcb_render_pictformat_t > visualHash