Split PixelLayout to separate source file

Change-Id: I0beafa39d92550ea78e78a07b25ce1253cc6668d
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2020-05-07 11:23:03 +02:00
parent 2ed048fa8d
commit 8a0f100e97
14 changed files with 1964 additions and 1875 deletions

View File

@ -183,6 +183,7 @@ qt_add_module(Gui
painting/qpdf.cpp painting/qpdf_p.h
painting/qpdfwriter.cpp painting/qpdfwriter.h
painting/qpen.cpp painting/qpen.h
painting/qpixellayout.cpp painting/qpixellayout_p.h
painting/qplatformbackingstore.cpp painting/qplatformbackingstore.h
painting/qpolygon.cpp painting/qpolygon.h
painting/qpolygonclipper_p.h

View File

@ -56,9 +56,9 @@
#include <limits.h>
#include <qpa/qplatformpixmap.h>
#include <private/qcolortransform_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qmemrotate_p.h>
#include <private/qimagescale_p.h>
#include <private/qpixellayout_p.h>
#include <private/qsimd_p.h>
#include <qhash.h>

View File

@ -37,10 +37,11 @@
**
****************************************************************************/
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
#include <private/qcolortrclut_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qendian_p.h>
#include <private/qpixellayout_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>

View File

@ -47,6 +47,7 @@ HEADERS += \
painting/qpdf_p.h \
painting/qpdfwriter.h \
painting/qpen.h \
painting/qpixellayout_p.h \
painting/qpolygon.h \
painting/qpolygonclipper_p.h \
painting/qrangecollection.h \
@ -100,6 +101,7 @@ SOURCES += \
painting/qpdf.cpp \
painting/qpdfwriter.cpp \
painting/qpen.cpp \
painting/qpixellayout.cpp \
painting/qpolygon.cpp \
painting/qrangecollection.cpp \
painting/qrasterizer.cpp \

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,7 @@
#include "qdrawhelper_p.h"
#include "qdrawhelper_x86_p.h"
#include "qdrawingprimitive_sse2_p.h"
#include "qpixellayout_p.h"
#include "qrgba64_p.h"
#if defined(QT_COMPILER_SUPPORTS_AVX2)

View File

@ -40,6 +40,7 @@
#include <private/qdrawhelper_neon_p.h>
#include <private/qblendfunctions_p.h>
#include <private/qmath_p.h>
#include <private/qpixellayout_p.h>
#ifdef __ARM_NEON__

View File

@ -61,6 +61,7 @@
#define QT_FT_BEGIN_HEADER
#define QT_FT_END_HEADER
#endif
#include "private/qpixellayout_p.h"
#include "private/qrasterdefs_p.h"
#include <private/qsimd_p.h>
@ -149,8 +150,6 @@ typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl,
const QTransform &targetRectTransform,
int const_alpha);
typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
struct DrawHelper {
ProcessSpans blendColor;
BitmapBlitFunc bitmapBlit;
@ -845,31 +844,6 @@ static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba6
}
#endif // __SSE2__
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
quint32 a = x << 24;
return a | rgb;
}
static Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) {
quint32 rgb = x << 8;
quint32 a = x >> 24;
return a | rgb;
}
#else
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
// RGBA8888 is ABGR32 on little endian.
quint32 ag = x & 0xff00ff00;
quint32 rg = x & 0x00ff00ff;
return ag | (rg << 16) | (rg >> 16);
}
static Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) {
return RGBA2ARGB(x);
}
#endif
static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16(uint x, uint a) {
a += 1;
uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
@ -889,14 +863,6 @@ static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257_floor(uint x) { return
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257(uint x) { return qt_div_257_floor(x + 128); }
static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; }
static Q_ALWAYS_INLINE uint qAlphaRgb30(uint c)
{
uint a = c >> 30;
a |= a << 2;
a |= a << 4;
return a;
}
template <class T> inline void qt_memfill_template(T *dest, T color, qsizetype count)
{
if (!count)
@ -978,214 +944,6 @@ inline QRgb qConvertRgb16To32(uint c)
| ((((c) << 8) & 0xf80000) | (((c) << 3) & 0x70000));
}
enum QtPixelOrder {
PixelOrderRGB,
PixelOrderBGR
};
template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb);
template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb);
template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c);
// A combined unpremultiply and premultiply with new simplified alpha.
// Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30).
template<unsigned int Shift>
inline QRgb qRepremultiply(QRgb p)
{
const uint alpha = qAlpha(p);
if (alpha == 255 || alpha == 0)
return p;
p = qUnpremultiply(p);
Q_CONSTEXPR uint mult = 255 / (255 >> Shift);
const uint newAlpha = mult * (alpha >> Shift);
p = (p & ~0xff000000) | (newAlpha<<24);
return qPremultiply(p);
}
template<unsigned int Shift>
inline QRgba64 qRepremultiply(QRgba64 p)
{
const uint alpha = p.alpha();
if (alpha == 65535 || alpha == 0)
return p;
p = p.unpremultiplied();
Q_CONSTEXPR uint mult = 65535 / (65535 >> Shift);
p.setAlpha(mult * (alpha >> Shift));
return p.premultiplied();
}
template<>
inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
{
c = qRepremultiply<6>(c);
return (c & 0xc0000000)
| (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
}
template<>
inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c)
{
c = qRepremultiply<6>(c);
return (c & 0xc0000000)
| (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
}
template<>
inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c)
{
return 0xc0000000
| (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
}
template<>
inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c)
{
return 0xc0000000
| (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
}
template<>
inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c)
{
uint a = c >> 30;
a |= a << 2;
a |= a << 4;
return (a << 24)
| ((c << 14) & 0x00ff0000)
| ((c >> 4) & 0x0000ff00)
| ((c >> 22) & 0x000000ff);
}
template<>
inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c)
{
uint a = c >> 30;
a |= a << 2;
a |= a << 4;
return (a << 24)
| ((c >> 6) & 0x00ff0000)
| ((c >> 4) & 0x0000ff00)
| ((c >> 2) & 0x000000ff);
}
template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb);
template<>
inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb)
{
quint16 alpha = rgb >> 30;
quint16 blue = (rgb >> 20) & 0x3ff;
quint16 green = (rgb >> 10) & 0x3ff;
quint16 red = rgb & 0x3ff;
// Expand the range.
alpha |= (alpha << 2);
alpha |= (alpha << 4);
alpha |= (alpha << 8);
red = (red << 6) | (red >> 4);
green = (green << 6) | (green >> 4);
blue = (blue << 6) | (blue >> 4);
return qRgba64(red, green, blue, alpha);
}
template<>
inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb)
{
quint16 alpha = rgb >> 30;
quint16 red = (rgb >> 20) & 0x3ff;
quint16 green = (rgb >> 10) & 0x3ff;
quint16 blue = rgb & 0x3ff;
// Expand the range.
alpha |= (alpha << 2);
alpha |= (alpha << 4);
alpha |= (alpha << 8);
red = (red << 6) | (red >> 4);
green = (green << 6) | (green >> 4);
blue = (blue << 6) | (blue >> 4);
return qRgba64(red, green, blue, alpha);
}
template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64);
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;
const uint b = c.blue() >> 6;
return (a << 30) | (b << 20) | (g << 10) | r;
}
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;
const uint b = c.blue() >> 6;
return (a << 30) | (r << 20) | (g << 10) | b;
}
inline uint qRgbSwapRgb30(uint c)
{
const uint ag = c & 0xc00ffc00;
const uint rb = c & 0x3ff003ff;
return ag | (rb << 20) | (rb >> 20);
}
inline int qRed565(quint16 rgb) {
const int r = (rgb & 0xf800);
return (r >> 8) | (r >> 13);
}
inline int qGreen565(quint16 rgb) {
const int g = (rgb & 0x07e0);
return (g >> 3) | (g >> 9);
}
inline int qBlue565(quint16 rgb) {
const int b = (rgb & 0x001f);
return (b << 3) | (b >> 2);
}
// We manually unalias the variables to make sure the compiler
// fully optimizes both aliased and unaliased cases.
#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
if (src == buffer) { \
for (int i = 0; i < count; ++i) \
buffer[i] = conversion(buffer[i]); \
} else { \
for (int i = 0; i < count; ++i) \
buffer[i] = conversion(src[i]); \
}
static Q_ALWAYS_INLINE const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
{
UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
return buffer;
}
static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
{
UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
return buffer;
}
template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
const uint qt_bayer_matrix[16][16] = {
{ 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
@ -1265,61 +1023,70 @@ struct IntermediateBuffer
quint32 buffer_ag[BufferSize+2];
};
struct QDitherInfo {
int x;
int y;
};
typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QVector<QRgb> *clut);
typedef void (QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QVector<QRgb> *clut);
typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
struct QPixelLayout
template <QPixelLayout::BPP bpp>
inline uint QT_FASTCALL qFetchPixel(const uchar *, int)
{
// Bits per pixel
enum BPP {
BPPNone,
BPP1MSB,
BPP1LSB,
BPP8,
BPP16,
BPP24,
BPP32,
BPP64,
BPPCount
Q_UNREACHABLE();
return 0;
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index)
{
return (src[index >> 3] >> (index & 7)) & 1;
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index)
{
return (src[index >> 3] >> (~index & 7)) & 1;
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP8>(const uchar *src, int index)
{
return src[index];
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP16>(const uchar *src, int index)
{
return reinterpret_cast<const quint16 *>(src)[index];
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP24>(const uchar *src, int index)
{
return reinterpret_cast<const quint24 *>(src)[index];
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP32>(const uchar *src, int index)
{
return reinterpret_cast<const uint *>(src)[index];
}
template <>
inline uint QT_FASTCALL qFetchPixel<QPixelLayout::BPP64>(const uchar *src, int index)
{
// We have to do the conversion in fetch to fit into a 32bit uint
QRgba64 c = reinterpret_cast<const QRgba64 *>(src)[index];
return c.toArgb32();
}
typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index);
constexpr FetchPixelFunc qFetchPixelTable[QPixelLayout::BPPCount] = {
nullptr, // BPPNone
qFetchPixel<QPixelLayout::BPP1MSB>,
qFetchPixel<QPixelLayout::BPP1LSB>,
qFetchPixel<QPixelLayout::BPP8>,
qFetchPixel<QPixelLayout::BPP16>,
qFetchPixel<QPixelLayout::BPP24>,
qFetchPixel<QPixelLayout::BPP32>,
qFetchPixel<QPixelLayout::BPP64>,
};
bool hasAlphaChannel;
bool premultiplied;
BPP bpp;
RbSwapFunc rbSwap;
ConvertFunc convertToARGB32PM;
ConvertTo64Func convertToRGBA64PM;
FetchAndConvertPixelsFunc fetchToARGB32PM;
FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
ConvertAndStorePixelsFunc storeFromARGB32PM;
ConvertAndStorePixelsFunc storeFromRGB32;
};
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
QT_END_NAMESPACE
#endif // QDRAWHELPER_P_H

View File

@ -40,6 +40,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpixellayout_p.h>
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)

View File

@ -37,7 +37,8 @@
**
****************************************************************************/
#include "private/qmemrotate_p.h"
#include "qmemrotate_p.h"
#include "qpixellayout_p.h"
QT_BEGIN_NAMESPACE

View File

@ -52,7 +52,7 @@
//
#include <QtGui/private/qtguiglobal_p.h>
#include "private/qdrawhelper_p.h"
#include <QtGui/private/qdrawhelper_p.h>
QT_BEGIN_NAMESPACE

View File

@ -62,8 +62,10 @@
#include <private/qimage_p.h>
#include <private/qstatictext_p.h>
#include <private/qcosmeticstroker_p.h>
#include "qmemrotate_p.h"
#include "qrgba64_p.h"
#include <private/qdrawhelper_p.h>
#include <private/qmemrotate_p.h>
#include <private/qpixellayout_p.h>
#include <private/qrgba64_p.h>
#include "qpaintengine_raster_p.h"
// #include "qbezier_p.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,336 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPIXELLAYOUT_P_H
#define QPIXELLAYOUT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qvector.h>
#include <QtGui/qimage.h>
#include <QtGui/qrgba64.h>
QT_BEGIN_NAMESPACE
enum QtPixelOrder {
PixelOrderRGB,
PixelOrderBGR
};
template<enum QtPixelOrder> inline uint qConvertArgb32ToA2rgb30(QRgb);
template<enum QtPixelOrder> inline uint qConvertRgb32ToRgb30(QRgb);
template<enum QtPixelOrder> inline QRgb qConvertA2rgb30ToArgb32(uint c);
// A combined unpremultiply and premultiply with new simplified alpha.
// Needed when alpha loses precision relative to other colors during conversion (ARGB32 -> A2RGB30).
template<unsigned int Shift>
inline QRgb qRepremultiply(QRgb p)
{
const uint alpha = qAlpha(p);
if (alpha == 255 || alpha == 0)
return p;
p = qUnpremultiply(p);
Q_CONSTEXPR uint mult = 255 / (255 >> Shift);
const uint newAlpha = mult * (alpha >> Shift);
p = (p & ~0xff000000) | (newAlpha<<24);
return qPremultiply(p);
}
template<unsigned int Shift>
inline QRgba64 qRepremultiply(QRgba64 p)
{
const uint alpha = p.alpha();
if (alpha == 65535 || alpha == 0)
return p;
p = p.unpremultiplied();
Q_CONSTEXPR uint mult = 65535 / (65535 >> Shift);
p.setAlpha(mult * (alpha >> Shift));
return p.premultiplied();
}
template<>
inline uint qConvertArgb32ToA2rgb30<PixelOrderBGR>(QRgb c)
{
c = qRepremultiply<6>(c);
return (c & 0xc0000000)
| (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
}
template<>
inline uint qConvertArgb32ToA2rgb30<PixelOrderRGB>(QRgb c)
{
c = qRepremultiply<6>(c);
return (c & 0xc0000000)
| (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
}
template<>
inline uint qConvertRgb32ToRgb30<PixelOrderBGR>(QRgb c)
{
return 0xc0000000
| (((c << 22) & 0x3fc00000) | ((c << 14) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c >> 14) & 0x000003fc) | ((c >> 22) & 0x00000003));
}
template<>
inline uint qConvertRgb32ToRgb30<PixelOrderRGB>(QRgb c)
{
return 0xc0000000
| (((c << 6) & 0x3fc00000) | ((c >> 2) & 0x00300000))
| (((c << 4) & 0x000ff000) | ((c >> 4) & 0x00000c00))
| (((c << 2) & 0x000003fc) | ((c >> 6) & 0x00000003));
}
template<>
inline QRgb qConvertA2rgb30ToArgb32<PixelOrderBGR>(uint c)
{
uint a = c >> 30;
a |= a << 2;
a |= a << 4;
return (a << 24)
| ((c << 14) & 0x00ff0000)
| ((c >> 4) & 0x0000ff00)
| ((c >> 22) & 0x000000ff);
}
template<>
inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c)
{
uint a = c >> 30;
a |= a << 2;
a |= a << 4;
return (a << 24)
| ((c >> 6) & 0x00ff0000)
| ((c >> 4) & 0x0000ff00)
| ((c >> 2) & 0x000000ff);
}
template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb);
template<>
inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb)
{
quint16 alpha = rgb >> 30;
quint16 blue = (rgb >> 20) & 0x3ff;
quint16 green = (rgb >> 10) & 0x3ff;
quint16 red = rgb & 0x3ff;
// Expand the range.
alpha |= (alpha << 2);
alpha |= (alpha << 4);
alpha |= (alpha << 8);
red = (red << 6) | (red >> 4);
green = (green << 6) | (green >> 4);
blue = (blue << 6) | (blue >> 4);
return qRgba64(red, green, blue, alpha);
}
template<>
inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb)
{
quint16 alpha = rgb >> 30;
quint16 red = (rgb >> 20) & 0x3ff;
quint16 green = (rgb >> 10) & 0x3ff;
quint16 blue = rgb & 0x3ff;
// Expand the range.
alpha |= (alpha << 2);
alpha |= (alpha << 4);
alpha |= (alpha << 8);
red = (red << 6) | (red >> 4);
green = (green << 6) | (green >> 4);
blue = (blue << 6) | (blue >> 4);
return qRgba64(red, green, blue, alpha);
}
template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64);
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;
const uint b = c.blue() >> 6;
return (a << 30) | (b << 20) | (g << 10) | r;
}
template<>
inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c)
{
c = qRepremultiply<14>(c);
const uint a = c.alpha() >> 14;
const uint r = c.red() >> 6;
const uint g = c.green() >> 6;
const uint b = c.blue() >> 6;
return (a << 30) | (r << 20) | (g << 10) | b;
}
inline uint qRgbSwapRgb30(uint c)
{
const uint ag = c & 0xc00ffc00;
const uint rb = c & 0x3ff003ff;
return ag | (rb << 20) | (rb >> 20);
}
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
quint32 a = x << 24;
return a | rgb;
}
Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) {
quint32 rgb = x << 8;
quint32 a = x >> 24;
return a | rgb;
}
#else
Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
// RGBA8888 is ABGR32 on little endian.
quint32 ag = x & 0xff00ff00;
quint32 rg = x & 0x00ff00ff;
return ag | (rg << 16) | (rg >> 16);
}
Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) {
return RGBA2ARGB(x);
}
#endif
// We manually unalias the variables to make sure the compiler
// fully optimizes both aliased and unaliased cases.
#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
if (src == buffer) { \
for (int i = 0; i < count; ++i) \
buffer[i] = conversion(buffer[i]); \
} else { \
for (int i = 0; i < count; ++i) \
buffer[i] = conversion(src[i]); \
}
inline const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
{
UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
return buffer;
}
inline const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
{
UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
return buffer;
}
template<bool RGBA> void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count);
struct QDitherInfo {
int x;
int y;
};
typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef const QRgba64 *(QT_FASTCALL *FetchAndConvertPixelsFunc64)(QRgba64 *buffer, const uchar *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc64)(uchar *dest, const QRgba64 *src, int index, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QVector<QRgb> *clut);
typedef void (QT_FASTCALL *Convert64Func)(quint64 *buffer, int count, const QVector<QRgb> *clut);
typedef const QRgba64 *(QT_FASTCALL *ConvertTo64Func)(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *clut, QDitherInfo *dither);
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl);
struct QPixelLayout
{
// Bits per pixel
enum BPP {
BPPNone,
BPP1MSB,
BPP1LSB,
BPP8,
BPP16,
BPP24,
BPP32,
BPP64,
BPPCount
};
bool hasAlphaChannel;
bool premultiplied;
BPP bpp;
RbSwapFunc rbSwap;
ConvertFunc convertToARGB32PM;
ConvertTo64Func convertToRGBA64PM;
FetchAndConvertPixelsFunc fetchToARGB32PM;
FetchAndConvertPixelsFunc64 fetchToRGBA64PM;
ConvertAndStorePixelsFunc storeFromARGB32PM;
ConvertAndStorePixelsFunc storeFromRGB32;
};
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
QT_END_NAMESPACE
#endif // QPIXELLAYOUT_P_H