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