1// Copyright (C) 2020 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#ifndef QPIXELLAYOUT_P_H
5#define QPIXELLAYOUT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qlist.h>
19#include <QtGui/qimage.h>
20#include <QtGui/qrgba64.h>
21#include <QtGui/qrgbafloat.h>
22#include <QtCore/private/qglobal_p.h>
23
24QT_BEGIN_NAMESPACE
25
26enum QtPixelOrder {
27 PixelOrderRGB,
28 PixelOrderBGR
29};
30
31template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb);
32
33template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb);
34
35template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c);
36
37// A combined unpremultiply and premultiply with new simplified alpha.
38// Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30).
39template<unsigned int Shift>
40inline QRgb qRepremultiply(QRgb p)
41{
42 const uint alpha = qAlpha(rgb: p);
43 if (alpha == 255 || alpha == 0)
44 return p;
45 p = qUnpremultiply(p);
46 constexpr uint mult = 255 / (255 >> Shift);
47 const uint newAlpha = mult * (alpha >> Shift);
48 p = (p & ~0xff000000) | (newAlpha<<24);
49 return qPremultiply(x: p);
50}
51
52template<unsigned int Shift>
53inline QRgba64 qRepremultiply(QRgba64 p)
54{
55 const uint alpha = p.alpha();
56 if (alpha == 65535 || alpha == 0)
57 return p;
58 p = p.unpremultiplied();
59 constexpr uint mult = 65535 / (65535 >> Shift);
60 p.setAlpha(mult * (alpha >> Shift));
61 return p.premultiplied();
62}
63
64template<>
65inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
66{
67 c = qRepremultiply<6>(p: c);
68 return (c & 0xc0000000)
69 | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
70 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
71 | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
72}
73
74template<>
75inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c)
76{
77 c = qRepremultiply<6>(p: c);
78 return (c & 0xc0000000)
79 | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
80 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
81 | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
82}
83
84template<>
85inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c)
86{
87 return 0xc0000000
88 | (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
89 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
90 | (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
91}
92
93template<>
94inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c)
95{
96 return 0xc0000000
97 | (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
98 | (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
99 | (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
100}
101
102template<>
103inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c)
104{
105 uint a = c >> 30;
106 a |= a << 2;
107 a |= a << 4;
108 return (a << 24)
109 | ((c << 14) & 0x00ff0000)
110 | ((c >> 4) & 0x0000ff00)
111 | ((c >> 22) & 0x000000ff);
112}
113
114template<>
115inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c)
116{
117 uint a = c >> 30;
118 a |= a << 2;
119 a |= a << 4;
120 return (a << 24)
121 | ((c >> 6) & 0x00ff0000)
122 | ((c >> 4) & 0x0000ff00)
123 | ((c >> 2) & 0x000000ff);
124}
125
126template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb);
127
128template<>
129inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb)
130{
131 quint16 alpha = rgb >> 30;
132 quint16 blue = (rgb >> 20) & 0x3ff;
133 quint16 green = (rgb >> 10) & 0x3ff;
134 quint16 red = rgb & 0x3ff;
135 // Expand the range.
136 alpha |= (alpha << 2);
137 alpha |= (alpha << 4);
138 alpha |= (alpha << 8);
139 red = (red << 6) | (red >> 4);
140 green = (green << 6) | (green >> 4);
141 blue = (blue << 6) | (blue >> 4);
142 return qRgba64(r: red, g: green, b: blue, a: alpha);
143}
144
145template<>
146inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb)
147{
148 quint16 alpha = rgb >> 30;
149 quint16 red = (rgb >> 20) & 0x3ff;
150 quint16 green = (rgb >> 10) & 0x3ff;
151 quint16 blue = rgb & 0x3ff;
152 // Expand the range.
153 alpha |= (alpha << 2);
154 alpha |= (alpha << 4);
155 alpha |= (alpha << 8);
156 red = (red << 6) | (red >> 4);
157 green = (green << 6) | (green >> 4);
158 blue = (blue << 6) | (blue >> 4);
159 return qRgba64(r: red, g: green, b: blue, a: alpha);
160}
161
162template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64);
163
164template<>
165inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
166{
167 c = qRepremultiply<14>(p: c);
168 const uint a = c.alpha() >> 14;
169 const uint r = c.red() >> 6;
170 const uint g = c.green() >> 6;
171 const uint b = c.blue() >> 6;
172 return (a << 30) | (b << 20) | (g << 10) | r;
173}
174
175template<>
176inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
177{
178 c = qRepremultiply<14>(p: c);
179 const uint a = c.alpha() >> 14;
180 const uint r = c.red() >> 6;
181 const uint g = c.green() >> 6;
182 const uint b = c.blue() >> 6;
183 return (a << 30) | (r << 20) | (g << 10) | b;
184}
185
186inline constexpr QRgbaFloat16 qConvertRgb64ToRgbaF16(QRgba64 c)
187{
188 return QRgbaFloat16::fromRgba64(red: c.red(), green: c.green(), blue: c.blue(), alpha: c.alpha());
189}
190
191inline constexpr QRgbaFloat32 qConvertRgb64ToRgbaF32(QRgba64 c)
192{
193 return QRgbaFloat32::fromRgba64(red: c.red(), green: c.green(), blue: c.blue(), alpha: c.alpha());
194}
195
196inline uint qRgbSwapRgb30(uint c)
197{
198 const uint ag = c & 0xc00ffc00;
199 const uint rb = c & 0x3ff003ff;
200 return ag | (rb << 20) | (rb >> 20);
201}
202
203#if Q_BYTE_ORDER == Q_BIG_ENDIAN
204static inline quint32 RGBA2ARGB(quint32 x) {
205 quint32 rgb = x >> 8;
206 quint32 a = x << 24;
207 return a | rgb;
208}
209
210static inline quint32 ARGB2RGBA(quint32 x) {
211 quint32 rgb = x << 8;
212 quint32 a = x >> 24;
213 return a | rgb;
214}
215#else
216static inline quint32 RGBA2ARGB(quint32 x) {
217 // RGBA8888 is ABGR32 on little endian.
218 quint32 ag = x & 0xff00ff00;
219 quint32 rg = x & 0x00ff00ff;
220 return ag | (rg << 16) | (rg >> 16);
221}
222
223static inline quint32 ARGB2RGBA(quint32 x) {
224 return RGBA2ARGB(x);
225}
226#endif
227
228// We manually unalias the variables to make sure the compiler
229// fully optimizes both aliased and unaliased cases.
230#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
231 if (src == buffer) { \
232 for (int i = 0; i < count; ++i) \
233 buffer[i] = conversion(buffer[i]); \
234 } else { \
235 for (int i = 0; i < count; ++i) \
236 buffer[i] = conversion(src[i]); \
237 }
238
239
240inline const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
241{
242 UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
243 return buffer;
244}
245
246inline const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
247{
248 UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
249 return buffer;
250}
251
252template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
253
254struct QDitherInfo {
255 int x;
256 int y;
257};
258
259typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src,
260 int index, int count,
261 const QList<QRgb> *clut,
262 QDitherInfo *dither);
263typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index,
264 int count, const QList<QRgb> *clut,
265 QDitherInfo *dither);
266
267typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src,
268 int index, int count,
269 const QList<QRgb> *clut,
270 QDitherInfo *dither);
271typedef void(QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index,
272 int count, const QList<QRgb> *clut,
273 QDitherInfo *dither);
274
275typedef const QRgbaFloat32 *(QT_FASTCALL *FetchAndConvertPixelsFuncFP)(QRgbaFloat32 *buffer, const uchar *src, int index, int count,
276 const QList<QRgb> *clut, QDitherInfo *dither);
277typedef void (QT_FASTCALL *ConvertAndStorePixelsFuncFP)(uchar *dest, const QRgbaFloat32 *src, int index, int count,
278 const QList<QRgb> *clut, QDitherInfo *dither);
279typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QList<QRgb> *clut);
280typedef void (QT_FASTCALL *Convert64Func)(QRgba64 *buffer, int count);
281typedef void (QT_FASTCALL *ConvertFPFunc)(QRgbaFloat32 *buffer, int count);
282typedef void (QT_FASTCALL *Convert64ToFPFunc)(QRgbaFloat32 *buffer, const quint64 *src, int count);
283
284typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
285 const QList<QRgb> *clut, QDitherInfo *dither);
286typedef const QRgbaFloat32 *(QT_FASTCALL *ConvertToFPFunc)(QRgbaFloat32 *buffer, const uint *src, int count,
287 const QList<QRgb> *clut, QDitherInfo *dither);
288typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
289
290typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
291
292struct QPixelLayout
293{
294 // Bits per pixel
295 enum BPP {
296 BPPNone,
297 BPP1MSB,
298 BPP1LSB,
299 BPP8,
300 BPP16,
301 BPP24,
302 BPP32,
303 BPP64,
304 BPP16FPx4,
305 BPP32FPx4,
306 BPPCount
307 };
308
309 bool hasAlphaChannel;
310 bool premultiplied;
311 BPP bpp;
312 RbSwapFunc rbSwap;
313 ConvertFunc convertToARGB32PM;
314 ConvertTo64Func convertToRGBA64PM;
315 FetchAndConvertPixelsFunc fetchToARGB32PM;
316 FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
317 ConvertAndStorePixelsFunc storeFromARGB32PM;
318 ConvertAndStorePixelsFunc storeFromRGB32;
319};
320
321extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
322
323#if QT_CONFIG(raster_fp)
324extern ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats];
325extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats];
326extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats];
327#endif
328
329extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
330
331extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
332
333QT_END_NAMESPACE
334
335#endif // QPIXELLAYOUT_P_H
336

source code of qtbase/src/gui/painting/qpixellayout_p.h