diff options
Diffstat (limited to 'src/gui/painting/qdrawhelper_p.h')
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 473 |
1 files changed, 97 insertions, 376 deletions
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index dd42b96d79..833ddd7b16 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDRAWHELPER_P_H #define QDRAWHELPER_P_H @@ -61,16 +25,17 @@ #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> -#include <QtCore/qsharedpointer.h> +#include <memory> QT_BEGIN_NAMESPACE #if defined(Q_CC_GNU) # define Q_DECL_RESTRICT __restrict__ -# if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) +# if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG) # define Q_DECL_VECTORCALL __attribute__((sseregparm,regparm(3))) # else # define Q_DECL_VECTORCALL @@ -88,13 +53,6 @@ static const uint RMASK = 0x00ff0000; static const uint GMASK = 0x0000ff00; static const uint BMASK = 0x000000ff; -/******************************************************************************* - * QSpan - * - * duplicate definition of FT_Span - */ -typedef QT_FT_Span QSpan; - struct QSolidData; struct QTextureData; struct QGradientData; @@ -107,6 +65,9 @@ class QRasterBuffer; class QClipData; class QRasterPaintEngineState; +template<typename F> class QRgbaFloat; +typedef QRgbaFloat<float> QRgbaFloat32; + typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 &color, @@ -149,8 +110,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; @@ -181,9 +140,9 @@ struct quint24 { uchar data[3]; }; -void qBlendGradient(int count, const QSpan *spans, void *userData); -void qBlendTexture(int count, const QSpan *spans, void *userData); -#ifdef __SSE2__ +void qBlendGradient(int count, const QT_FT_Span *spans, void *userData); +void qBlendTexture(int count, const QT_FT_Span *spans, void *userData); +#ifdef Q_PROCESSOR_X86 extern void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count); extern void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count); #else @@ -195,8 +154,10 @@ extern void qt_memfill16(quint16 *dest, quint16 value, qsizetype count); typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunctionFP)(QRgbaFloat32 *Q_DECL_RESTRICT dest, const QRgbaFloat32 *Q_DECL_RESTRICT src, int length, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunctionSolidFP)(QRgbaFloat32 *dest, int length, QRgbaFloat32 color, uint const_alpha); struct LinearGradientValues { @@ -213,17 +174,19 @@ struct RadialGradientValues qreal dr; qreal sqrfr; qreal a; - qreal inv2a; bool extended; }; struct Operator; typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); +typedef QRgbaFloat32* (QT_FASTCALL *DestFetchProcFP)(QRgbaFloat32 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length); +typedef void (QT_FASTCALL *DestStoreProcFP)(QRasterBuffer *rasterBuffer, int x, int y, const QRgbaFloat32 *buffer, int length); typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); +typedef const QRgbaFloat32* (QT_FASTCALL *SourceFetchProcFP)(QRgbaFloat32 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); struct Operator { @@ -240,6 +203,12 @@ struct Operator CompositionFunctionSolid64 funcSolid64; CompositionFunction64 func64; + DestFetchProcFP destFetchFP; + DestStoreProcFP destStoreFP; + SourceFetchProcFP srcFetchFP; + CompositionFunctionSolidFP funcSolidFP; + CompositionFunctionFP funcFP; + union { LinearGradientValues linear; RadialGradientValues radial; @@ -296,7 +265,7 @@ struct QGradientData #define GRADIENT_STOPTABLE_SIZE 1024 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10 -#if QT_CONFIG(raster_64bit) +#if QT_CONFIG(raster_64bit) || QT_CONFIG(raster_fp) const QRgba64 *colorTable64; //[GRADIENT_STOPTABLE_SIZE]; #endif const QRgb *colorTable32; //[GRADIENT_STOPTABLE_SIZE]; @@ -318,11 +287,12 @@ struct QTextureData int y2; qsizetype bytesPerLine; QImage::Format format; - const QVector<QRgb> *colorTable; + const QList<QRgb> *colorTable; bool hasAlpha; enum Type { Plain, - Tiled + Tiled, + Pattern }; Type type; int const_alpha; @@ -350,24 +320,20 @@ struct QSpanData ConicalGradient, Texture } type : 8; - int txop : 8; - int fast_matrix : 1; + signed int txop : 8; + uint fast_matrix : 1; bool bilinear; QImage *tempImage; - QRgba64 solidColor; + QColor solidColor; union { QGradientData gradient; QTextureData texture; }; - class Pinnable { - protected: - ~Pinnable() {} - }; // QSharedPointer<const void> is not supported - QSharedPointer<const Pinnable> cachedGradient; + std::shared_ptr<const void> cachedGradient; void init(QRasterBuffer *rb, const QRasterPaintEngine *pe); - void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode); + void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode, bool isCosmetic); void setupMatrix(const QTransform &matrix, int bilinear); void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect()); void adjustSpanMethods(); @@ -435,12 +401,12 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe bool affine = !data->m13 && !data->m23; BlendType *end = buffer + length; + qreal inv_a = 1 / qreal(2 * op->radial.a); + if (affine) { rx -= data->gradient.radial.focal.x; ry -= data->gradient.radial.focal.y; - qreal inv_a = 1 / qreal(2 * op->radial.a); - const qreal delta_rx = data->m11; const qreal delta_ry = data->m12; @@ -473,7 +439,7 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe while (buffer < end) { if (rw == 0) { - *buffer = 0; + *buffer = RadialFetchFunc::null(); } else { qreal invRw = 1 / rw; qreal gx = rx * invRw - data->gradient.radial.focal.x; @@ -485,8 +451,8 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe if (det >= 0) { qreal detSqrt = qSqrt(det); - qreal s0 = (-b - detSqrt) * op->radial.inv2a; - qreal s1 = (-b + detSqrt) * op->radial.inv2a; + qreal s0 = (-b - detSqrt) * inv_a; + qreal s1 = (-b + detSqrt) * inv_a; qreal s = qMax(s0, s1); @@ -601,12 +567,12 @@ public: FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD) break; default: - Q_ASSERT(false); + Q_UNREACHABLE(); } } }; -static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { +static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; t &= 0xff00ff; @@ -620,7 +586,7 @@ static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b #if Q_PROCESSOR_WORDSIZE == 8 // 64-bit versions -static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t += (((quint64(y)) | ((quint64(y)) << 24)) & 0x00ff00ff00ff00ff) * b; t >>= 8; @@ -628,7 +594,7 @@ static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b return (uint(t)) | (uint(t >> 24)); } -static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { +static inline uint BYTE_MUL(uint x, uint a) { quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8; t &= 0x00ff00ff00ff00ff; @@ -637,7 +603,7 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { #else // 32-bit versions -static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { +static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; t >>= 8; t &= 0xff00ff; @@ -648,7 +614,7 @@ static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b return x; } -static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { +static inline uint BYTE_MUL(uint x, uint a) { uint t = (x & 0xff00ff) * a; t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; t &= 0xff00ff; @@ -661,7 +627,7 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { } #endif -static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src) +static inline void blend_pixel(quint32 &dst, const quint32 src) { if (src >= 0xff000000) dst = src; @@ -669,7 +635,7 @@ static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src) dst = src + BYTE_MUL(dst, qAlpha(~src)); } -static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src, const int const_alpha) +static inline void blend_pixel(quint32 &dst, const quint32 src, const int const_alpha) { if (const_alpha == 255) return blend_pixel(dst, src); @@ -680,7 +646,7 @@ static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src, const i } #if defined(__SSE2__) -static Q_ALWAYS_INLINE uint interpolate_4_pixels_sse2(__m128i vt, __m128i vb, uint distx, uint disty) +static inline uint Q_DECL_VECTORCALL interpolate_4_pixels_sse2(__m128i vt, __m128i vb, uint distx, uint disty) { // First interpolate top and bottom pixels in parallel. vt = _mm_unpacklo_epi8(vt, _mm_setzero_si128()); @@ -721,7 +687,7 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis static constexpr inline bool hasFastInterpolate4() { return true; } #elif defined(__ARM_NEON__) -static Q_ALWAYS_INLINE uint interpolate_4_pixels_neon(uint32x2_t vt32, uint32x2_t vb32, uint distx, uint disty) +static inline uint interpolate_4_pixels_neon(uint32x2_t vt32, uint32x2_t vb32, uint distx, uint disty) { uint16x8_t vt16 = vmovl_u8(vreinterpret_u8_u32(vt32)); uint16x8_t vb16 = vmovl_u8(vreinterpret_u8_u32(vb32)); @@ -845,57 +811,75 @@ 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; +#if QT_CONFIG(raster_fp) +static inline QRgbaFloat32 multiplyAlpha_rgba32f(QRgbaFloat32 c, float a) +{ + return QRgbaFloat32 { c.r * a, c.g * a, c.b * a, c.a * a }; } -static Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) { - quint32 rgb = x << 8; - quint32 a = x >> 24; - return a | rgb; +static inline QRgbaFloat32 interpolate_rgba32f(QRgbaFloat32 x, float alpha1, QRgbaFloat32 y, float alpha2) +{ + x = multiplyAlpha_rgba32f(x, alpha1); + y = multiplyAlpha_rgba32f(y, alpha2); + return QRgbaFloat32 { x.r + y.r, x.g + y.g, x.b + y.b, x.a + y.a }; } -#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); +#ifdef __SSE2__ +static inline __m128 Q_DECL_VECTORCALL interpolate_rgba32f(__m128 x, __m128 alpha1, __m128 y, __m128 alpha2) +{ + return _mm_add_ps(_mm_mul_ps(x, alpha1), _mm_mul_ps(y, alpha2)); } +#endif -static Q_ALWAYS_INLINE quint32 ARGB2RGBA(quint32 x) { - return RGBA2ARGB(x); -} +static inline QRgbaFloat32 interpolate_4_pixels_rgba32f(const QRgbaFloat32 t[], const QRgbaFloat32 b[], uint distx, uint disty) +{ + constexpr float f = 1.0f / 65536.0f; + const float dx = distx * f; + const float dy = disty * f; + const float idx = 1.0f - dx; + const float idy = 1.0f - dy; +#ifdef __SSE2__ + const __m128 vtl = _mm_load_ps((const float *)&t[0]); + const __m128 vtr = _mm_load_ps((const float *)&t[1]); + const __m128 vbl = _mm_load_ps((const float *)&b[0]); + const __m128 vbr = _mm_load_ps((const float *)&b[1]); + + const __m128 vdx = _mm_set1_ps(dx); + const __m128 vidx = _mm_set1_ps(idx); + __m128 vt = interpolate_rgba32f(vtl, vidx, vtr, vdx); + __m128 vb = interpolate_rgba32f(vbl, vidx, vbr, vdx); + const __m128 vdy = _mm_set1_ps(dy); + const __m128 vidy = _mm_set1_ps(idy); + vt = interpolate_rgba32f(vt, vidy, vb, vdy); + QRgbaFloat32 res; + _mm_store_ps((float*)&res, vt); + return res; +#else + QRgbaFloat32 xtop = interpolate_rgba32f(t[0], idx, t[1], dx); + QRgbaFloat32 xbot = interpolate_rgba32f(b[0], idx, b[1], dx); + xtop = interpolate_rgba32f(xtop, idy, xbot, dy); + return xtop; #endif +} +#endif // QT_CONFIG(raster_fp) -static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16(uint x, uint a) { +static inline uint BYTE_MUL_RGB16(uint x, uint a) { a += 1; uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0; t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f; return t; } -static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { +static inline uint BYTE_MUL_RGB16_32(uint x, uint a) { uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0; t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f; return t; } // qt_div_255 is a fast rounded division by 255 using an approximation that is accurate for all positive 16-bit integers -static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } -static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } -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; -} +static constexpr inline int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static constexpr inline uint qt_div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } +static constexpr inline uint qt_div_257(uint x) { return qt_div_257_floor(x + 128); } +static constexpr inline uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } template <class T> inline void qt_memfill_template(T *dest, T color, qsizetype count) { @@ -978,214 +962,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}, @@ -1250,7 +1026,7 @@ inline uint comp_func_Plus_one_pixel(uint d, const uint s) #undef AMIX // must be multiple of 4 for easier SIMD implementations -static Q_CONSTEXPR int BufferSize = 2048; +static constexpr int BufferSize = 2048; // A buffer of intermediate results used by simple bilinear scaling. struct IntermediateBuffer @@ -1265,61 +1041,6 @@ 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 -{ - // 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 // QDRAWHELPER_P_H |