Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxcbimage.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qxcbimage.h"
5#include <QtCore/QtEndian>
6#include <QtGui/QColor>
7#include <QtGui/private/qimage_p.h>
8#include <QtGui/private/qdrawhelper_p.h>
9
10#include <xcb/render.h>
11#include <xcb/xcb_renderutil.h>
12
13#include "qxcbconnection.h"
14#include "qxcbintegration.h"
15
16namespace {
17
18QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask, int blue_mask)
19{
20 if (bits_per_pixel == 32) {
21 switch (depth) {
22 case 32:
23 if (red_mask == 0xff0000 && blue_mask == 0xff)
25#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
26 if (red_mask == 0xff && blue_mask == 0xff0000)
28#else
29 if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00)
31#endif
32 if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
34 if (red_mask == 0x3ff00000 && blue_mask == 0x3ff)
36 break;
37 case 30:
38 if (red_mask == 0x3ff && blue_mask == 0x3ff00000)
40 if (blue_mask == 0x3ff && red_mask == 0x3ff00000)
42 break;
43 case 24:
44 if (red_mask == 0xff0000 && blue_mask == 0xff)
46#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
47 if (red_mask == 0xff && blue_mask == 0xff0000)
49#else
50 if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00)
52#endif
53 break;
54 }
55 } else if (bits_per_pixel == 16) {
56 if (depth == 16 && red_mask == 0xf800 && blue_mask == 0x1f)
58 if (depth == 15 && red_mask == 0x7c00 && blue_mask == 0x1f)
60 }
62}
63
64} // namespace
65
67
68bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual,
69 QImage::Format *imageFormat, bool *needsRgbSwap)
70{
71 Q_ASSERT(connection && visual && imageFormat);
72
73 if (needsRgbSwap)
74 *needsRgbSwap = false;
75 *imageFormat = QImage::Format_Invalid;
76
77 if (depth == 8) {
78 if (visual->_class == XCB_VISUAL_CLASS_GRAY_SCALE) {
79 *imageFormat = QImage::Format_Grayscale8;
80 return true;
81 }
82#if QT_CONFIG(xcb_native_painting)
83 if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled()) {
84 *imageFormat = QImage::Format_Indexed8;
85 return true;
86 }
87#endif
88 return false;
89 }
90
91 const xcb_format_t *format = connection->formatForDepth(depth);
92 if (!format)
93 return false;
94
95 const bool connectionEndianSwap = connection->imageNeedsEndianSwap();
96 // We swap the masks and see if we can recognize it as a host format
97 const quint32 red_mask = connectionEndianSwap ? qbswap(visual->red_mask) : visual->red_mask;
98 const quint32 blue_mask = connectionEndianSwap ? qbswap(visual->blue_mask) : visual->blue_mask;
99
100 *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, red_mask, blue_mask);
101 if (*imageFormat != QImage::Format_Invalid)
102 return true;
103
104 if (needsRgbSwap) {
105 *imageFormat = imageFormatForMasks(depth, format->bits_per_pixel, blue_mask, red_mask);
106 if (*imageFormat != QImage::Format_Invalid) {
107 *needsRgbSwap = true;
108 return true;
109 }
110 }
111
112 qWarning("Unsupported screen format: depth: %d, bits_per_pixel: %d, red_mask: %x, blue_mask: %x", depth, format->bits_per_pixel, red_mask, blue_mask);
113
114 return false;
115}
116
118 int width, int height, int depth,
119 const xcb_visualtype_t *visual)
120{
121 xcb_connection_t *conn = connection->xcb_connection();
122
123 auto image_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_image, conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap,
124 0, 0, width, height, 0xffffffff);
125 if (!image_reply) {
126 return QPixmap();
127 }
128
129 uint8_t *data = xcb_get_image_data(image_reply.get());
130 uint32_t length = xcb_get_image_data_length(image_reply.get());
131
133
135 bool needsRgbSwap;
136 if (qt_xcb_imageFormatForVisual(connection, depth, visual, &format, &needsRgbSwap)) {
137 uint32_t bytes_per_line = length / height;
138 QImage image(const_cast<uint8_t *>(data), width, height, bytes_per_line, format);
139
140 if (needsRgbSwap)
141 image = std::move(image).rgbSwapped();
142
143 // fix-up alpha channel
145 QRgb *p = (QRgb *)image.bits();
146 for (int y = 0; y < height; ++y) {
147 for (int x = 0; x < width; ++x)
148 p[x] |= 0xff000000;
149 p += bytes_per_line / 4;
150 }
152 QRgb *p = (QRgb *)image.bits();
153 for (int y = 0; y < height; ++y) {
154 for (int x = 0; x < width; ++x)
155 p[x] |= 0xc0000000;
156 p += bytes_per_line / 4;
157 }
158 }
159
161 }
162
163 return result;
164}
165
167{
168 xcb_connection_t *conn = screen->xcb_connection();
169 QImage bitmap = image.convertToFormat(QImage::Format_MonoLSB);
170 const QRgb c0 = QColor(Qt::black).rgb();
171 const QRgb c1 = QColor(Qt::white).rgb();
172 if (bitmap.color(0) == c0 && bitmap.color(1) == c1) {
173 bitmap.invertPixels();
174 bitmap.setColor(0, c1);
175 bitmap.setColor(1, c0);
176 }
177 const int width = bitmap.width();
178 const int height = bitmap.height();
179 const qsizetype bytesPerLine = bitmap.bytesPerLine();
180 int destLineSize = width / 8;
181 if (width % 8)
182 ++destLineSize;
183 const uchar *map = bitmap.bits();
184 uint8_t *buf = new uint8_t[height * destLineSize];
185 for (int i = 0; i < height; i++)
186 memcpy(buf + (destLineSize * i), map + (bytesPerLine * i), destLineSize);
187 xcb_pixmap_t pm = xcb_create_pixmap_from_bitmap_data(conn, screen->root(), buf,
188 width, height, 1, 0, 0, nullptr);
189 delete[] buf;
190 return pm;
191}
192
194 const QPoint &spot)
195{
196 xcb_connection_t *conn = screen->xcb_connection();
197 const int w = image.width();
198 const int h = image.height();
199 auto formats = Q_XCB_REPLY(xcb_render_query_pict_formats, conn);
200 if (!formats) {
201 qWarning("qt_xcb_createCursorXRender: query_pict_formats failed");
202 return XCB_NONE;
203 }
204 xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formats.get(),
205 XCB_PICT_STANDARD_ARGB_32);
206 if (!fmt) {
207 qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
208 return XCB_NONE;
209 }
210
212 xcb_image_t *xi = xcb_image_create(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
213 32, 32, 32, 32,
214 QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST,
215 XCB_IMAGE_ORDER_MSB_FIRST,
216 nullptr, 0, nullptr);
217 if (!xi) {
218 qWarning("qt_xcb_createCursorXRender: xcb_image_create failed");
219 return XCB_NONE;
220 }
221 xi->data = (uint8_t *) malloc(xi->stride * h);
222 if (!xi->data) {
223 qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data");
224 xcb_image_destroy(xi);
225 return XCB_NONE;
226 }
227 memcpy(xi->data, img.constBits(), img.sizeInBytes());
228
229 xcb_pixmap_t pix = xcb_generate_id(conn);
230 xcb_create_pixmap(conn, 32, pix, screen->root(), w, h);
231
232 xcb_render_picture_t pic = xcb_generate_id(conn);
233 xcb_render_create_picture(conn, pic, pix, fmt->id, 0, nullptr);
234
235 xcb_gcontext_t gc = xcb_generate_id(conn);
236 xcb_create_gc(conn, gc, pix, 0, nullptr);
237 xcb_image_put(conn, pix, gc, xi, 0, 0, 0);
238 xcb_free_gc(conn, gc);
239
240 xcb_cursor_t cursor = xcb_generate_id(conn);
241 xcb_render_create_cursor(conn, cursor, pic, spot.x(), spot.y());
242
243 free(xi->data);
244 xcb_image_destroy(xi);
245 xcb_render_free_picture(conn, pic);
246 xcb_free_pixmap(conn, pix);
247 return cursor;
248}
249
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QRgb rgb() const noexcept
Returns the RGB value of the color.
Definition qcolor.cpp:1439
\inmodule QtGui
Definition qimage.h:37
Format
The following image formats are available in Qt.
Definition qimage.h:41
@ Format_RGB30
Definition qimage.h:63
@ Format_RGB32
Definition qimage.h:46
@ Format_Invalid
Definition qimage.h:42
@ Format_MonoLSB
Definition qimage.h:44
@ Format_RGBA8888_Premultiplied
Definition qimage.h:60
@ Format_RGB555
Definition qimage.h:53
@ Format_A2BGR30_Premultiplied
Definition qimage.h:62
@ Format_Indexed8
Definition qimage.h:45
@ Format_BGR30
Definition qimage.h:61
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
@ Format_A2RGB30_Premultiplied
Definition qimage.h:64
@ Format_RGB16
Definition qimage.h:49
@ Format_RGBX8888
Definition qimage.h:58
@ Format_Grayscale8
Definition qimage.h:66
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition qpixmap.cpp:1437
\inmodule QtCore\reentrant
Definition qpoint.h:25
@ BigEndian
Definition qsysinfo.h:29
@ ByteOrder
Definition qsysinfo.h:34
static QXcbIntegration * instance()
QMap< QString, QString > map
[6]
QCursor cursor
QPixmap pix
EGLint EGLint * formats
Combined button and popup list for selecting options.
@ white
Definition qnamespace.h:31
@ black
Definition qnamespace.h:30
Definition image.cpp:4
DBusConnection * connection
constexpr T qbswap(T source)
Definition qendian.h:103
#define qWarning
Definition qlogging.h:166
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLint void * img
Definition qopenglext.h:233
GLsizei GLfixed GLfixed GLfixed GLfixed const GLubyte * bitmap
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
QScreen * screen
[1]
Definition main.cpp:29
void gc(QV4::ExecutionEngine &engine, GCFlags flags)
Definition qmlutils.cpp:118
unsigned int quint32
Definition qtypes.h:50
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qsizetype
Definition qtypes.h:165
QVideoFrameFormat::PixelFormat fmt
#define Q_XCB_REPLY(call,...)
#define Q_XCB_REPLY_UNCHECKED(call,...)
xcb_pixmap_t qt_xcb_XPixmapFromBitmap(QXcbScreen *screen, const QImage &image)
QT_BEGIN_NAMESPACE bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, const xcb_visualtype_t *visual, QImage::Format *imageFormat, bool *needsRgbSwap)
Definition qxcbimage.cpp:68
xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, const QPoint &spot)
QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap, int width, int height, int depth, const xcb_visualtype_t *visual)
widget render & pixmap