diff options
Diffstat (limited to 'src/gui/painting/qdrawhelper.cpp')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 257 |
1 files changed, 92 insertions, 165 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index ae62aeca5f..08f96bd654 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -218,8 +218,8 @@ static const QRgba64 *QT_FASTCALL convertToRGB64(QRgba64 *buffer, const uint *sr uint green = (src[i] >> greenShift<Format>()) & greenMask; uint blue = (src[i] >> blueShift<Format>()) & blueMask; - red = ((red << redLeftShift) | (red >> redRightShift)) << 16; - green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8; + red = ((red << redLeftShift) | (red >> redRightShift)); + green = ((green << greenLeftShift) | (green >> greenRightShift)); blue = (blue << blueLeftShift) | (blue >> blueRightShift); buffer[i] = QRgba64::fromRgba(red, green, blue, 255); } @@ -581,6 +581,8 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint * int i = 0; for (; ((uintptr_t)buffer & 0xf) && i < count; ++i) { uint s = *src++; + if (maskAlpha) + s = s | 0xff000000; if (RGBA) s = RGBA2ARGB(s); *buffer++ = QRgba64::fromArgb32(s); @@ -606,6 +608,8 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint * SIMD_EPILOGUE(i, count, 3) { uint s = *src++; + if (maskAlpha) + s = s | 0xff000000; if (RGBA) s = RGBA2ARGB(s); *buffer++ = QRgba64::fromArgb32(s); @@ -837,7 +841,10 @@ static const uint *QT_FASTCALL convertGrayscale8FromARGB32PM(uint *buffer, const } template <QPixelLayout::BPP bpp> static -uint QT_FASTCALL fetchPixel(const uchar *src, int index); +uint QT_FASTCALL fetchPixel(const uchar *, int) +{ + Q_UNREACHABLE(); +} template <> inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index) @@ -1555,102 +1562,28 @@ static const QRgba64 *QT_FASTCALL fetchUntransformed64(QRgba64 *buffer, const Op } } -// blendType is either BlendTransformed or BlendTransformedTiled -template<TextureBlendType blendType> -static const uint *QT_FASTCALL fetchTransformedARGB32PM(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) -{ - int image_width = data->texture.width; - int image_height = data->texture.height; - - const qreal cx = x + qreal(0.5); - const qreal cy = y + qreal(0.5); - - const uint *end = buffer + length; - uint *b = buffer; - if (data->fast_matrix) { - // The increment pr x in the scanline - int fdx = (int)(data->m11 * fixed_scale); - int fdy = (int)(data->m12 * fixed_scale); - - int fx = int((data->m21 * cy - + data->m11 * cx + data->dx) * fixed_scale); - int fy = int((data->m22 * cy - + data->m12 * cx + data->dy) * fixed_scale); - - while (b < end) { - int px = fx >> 16; - int py = fy >> 16; - - if (blendType == BlendTransformedTiled) { - px %= image_width; - py %= image_height; - if (px < 0) px += image_width; - if (py < 0) py += image_height; - } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); - } - *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; - - fx += fdx; - fy += fdy; - ++b; - } - } else { - const qreal fdx = data->m11; - const qreal fdy = data->m12; - const qreal fdw = data->m13; - - qreal fx = data->m21 * cy + data->m11 * cx + data->dx; - qreal fy = data->m22 * cy + data->m12 * cx + data->dy; - qreal fw = data->m23 * cy + data->m13 * cx + data->m33; - - while (b < end) { - const qreal iw = fw == 0 ? 1 : 1 / fw; - const qreal tx = fx * iw; - const qreal ty = fy * iw; - int px = int(tx) - (tx < 0); - int py = int(ty) - (ty < 0); - - if (blendType == BlendTransformedTiled) { - px %= image_width; - py %= image_height; - if (px < 0) px += image_width; - if (py < 0) py += image_height; - } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); - } - *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; - - fx += fdx; - fy += fdy; - fw += fdw; - //force increment to avoid /0 - if (!fw) { - fw += fdw; - } - ++b; - } - } - return buffer; -} - -template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ +template<TextureBlendType blendType, QPixelLayout::BPP bpp> static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length) { - int image_width = data->texture.width; - int image_height = data->texture.height; + Q_STATIC_ASSERT(blendType == BlendTransformed || blendType == BlendTransformedTiled); + const int image_width = data->texture.width; + const int image_height = data->texture.height; + const int image_x1 = data->texture.x1; + const int image_y1 = data->texture.y1; + const int image_x2 = data->texture.x2 - 1; + const int image_y2 = data->texture.y2 - 1; const qreal cx = x + qreal(0.5); const qreal cy = y + qreal(0.5); const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; - FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 + Q_ASSERT(layout->bpp == bpp); + // When templated 'fetch' should be inlined at compile time: + const FetchPixelFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; - const uint *end = buffer + length; + uint *const end = buffer + length; uint *b = buffer; if (data->fast_matrix) { // The increment pr x in the scanline @@ -1672,8 +1605,8 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, if (px < 0) px += image_width; if (py < 0) py += image_height; } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); + px = qBound(image_x1, px, image_x2); + py = qBound(image_y1, py, image_y2); } *b = fetch(data->texture.scanLine(py), px); @@ -1703,8 +1636,8 @@ static const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, if (px < 0) px += image_width; if (py < 0) py += image_height; } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); + px = qBound(image_x1, px, image_x2); + py = qBound(image_y1, py, image_y2); } *b = fetch(data->texture.scanLine(py), px); @@ -1725,8 +1658,12 @@ template<TextureBlendType blendType> /* either BlendTransformed or BlendTransfo static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Operator *, const QSpanData *data, int y, int x, int length) { - int image_width = data->texture.width; - int image_height = data->texture.height; + const int image_width = data->texture.width; + const int image_height = data->texture.height; + const int image_x1 = data->texture.x1; + const int image_y1 = data->texture.y1; + const int image_x2 = data->texture.x2 - 1; + const int image_y2 = data->texture.y2 - 1; const qreal cx = x + qreal(0.5); const qreal cy = y + qreal(0.5); @@ -1763,8 +1700,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper if (px < 0) px += image_width; if (py < 0) py += image_height; } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); + px = qBound(image_x1, px, image_x2); + py = qBound(image_y1, py, image_y2); } buffer32[j] = fetch(data->texture.scanLine(py), px); @@ -1804,8 +1741,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformed64(QRgba64 *buffer, const Oper if (px < 0) px += image_width; if (py < 0) py += image_height; } else { - px = qBound(0, px, image_width - 1); - py = qBound(0, py, image_height - 1); + px = qBound(image_x1, px, image_x2); + py = qBound(image_y1, py, image_y2); } buffer32[j] = fetch(data->texture.scanLine(py), px); @@ -2307,7 +2244,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c } } } else { //rotation - if (std::abs(data->m11) > 8 || std::abs(data->m22) > 8) { + if (std::abs(data->m11) < (1./8.) || std::abs(data->m22) < (1./8.)) { //if we are zooming more than 8 times, we use 8bit precision for the position. while (b < end) { int x1 = (fx >> 16); @@ -2586,12 +2523,17 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c } // blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled -template<TextureBlendType blendType> +template<TextureBlendType blendType, QPixelLayout::BPP bpp> static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length) { const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; const QVector<QRgb> *clut = data->texture.colorTable; + if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1 + Q_ASSERT(layout->bpp == bpp); + // When templated 'fetch' should be inlined at compile time: + const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : fetchPixels<bpp>; + const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>; int image_width = data->texture.width; int image_height = data->texture.height; @@ -2629,7 +2571,6 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper // The idea is first to do the interpolation between the row s1 and the row s2 // into an intermediate buffer, then we interpolate between two pixel of this buffer. - FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; // +1 for the last pixel to interpolate with, and +1 for rounding errors. uint buf1[buffer_size + 2]; uint buf2[buffer_size + 2]; @@ -2718,7 +2659,6 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper fx += fdx; } } else { - FetchPixelFunc fetch = qFetchPixel[layout->bpp]; uint buf1[buffer_size]; uint buf2[buffer_size]; uint *b = buffer; @@ -2729,19 +2669,10 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper int x1 = (fx >> 16); int x2; fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); - - if (layout->bpp == QPixelLayout::BPP32) { - buf1[i * 2 + 0] = ((const uint*)s1)[x1]; - buf1[i * 2 + 1] = ((const uint*)s1)[x2]; - buf2[i * 2 + 0] = ((const uint*)s2)[x1]; - buf2[i * 2 + 1] = ((const uint*)s2)[x2]; - } else { - buf1[i * 2 + 0] = fetch(s1, x1); - buf1[i * 2 + 1] = fetch(s1, x2); - buf2[i * 2 + 0] = fetch(s2, x1); - buf2[i * 2 + 1] = fetch(s2, x2); - } - + buf1[i * 2 + 0] = fetch1(s1, x1); + buf1[i * 2 + 1] = fetch1(s1, x2); + buf2[i * 2 + 0] = fetch1(s2, x1); + buf2[i * 2 + 1] = fetch1(s2, x2); fx += fdx; } layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); @@ -2771,7 +2702,6 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper } } } else { //rotation - FetchPixelFunc fetch = qFetchPixel[layout->bpp]; uint buf1[buffer_size]; uint buf2[buffer_size]; uint *b = buffer; @@ -2790,26 +2720,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); - - if (layout->bpp == QPixelLayout::BPP32) { - buf1[i * 2 + 0] = ((const uint*)s1)[x1]; - buf1[i * 2 + 1] = ((const uint*)s1)[x2]; - buf2[i * 2 + 0] = ((const uint*)s2)[x1]; - buf2[i * 2 + 1] = ((const uint*)s2)[x2]; - } else { - buf1[i * 2 + 0] = fetch(s1, x1); - buf1[i * 2 + 1] = fetch(s1, x2); - buf2[i * 2 + 0] = fetch(s2, x1); - buf2[i * 2 + 1] = fetch(s2, x2); - } - + buf1[i * 2 + 0] = fetch1(s1, x1); + buf1[i * 2 + 1] = fetch1(s1, x2); + buf2[i * 2 + 0] = fetch1(s2, x1); + buf2[i * 2 + 1] = fetch1(s2, x2); fx += fdx; fy += fdy; } layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0); - if (std::abs(data->m11) > 8 || std::abs(data->m22) > 8) { + if (std::abs(data->m11) < (1./8.) || std::abs(data->m22) < (1./8.)) { //if we are zooming more than 8 times, we use 8bit precision for the position. for (int i = 0; i < len; ++i) { int distx = (fracX & 0x0000ffff) >> 8; @@ -2849,7 +2770,6 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper qreal fy = data->m22 * cy + data->m12 * cx + data->dy; qreal fw = data->m23 * cy + data->m13 * cx + data->m33; - FetchPixelFunc fetch = qFetchPixel[layout->bpp]; uint buf1[buffer_size]; uint buf2[buffer_size]; uint *b = buffer; @@ -2877,18 +2797,10 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); - - if (layout->bpp == QPixelLayout::BPP32) { - buf1[i * 2 + 0] = ((const uint*)s1)[x1]; - buf1[i * 2 + 1] = ((const uint*)s1)[x2]; - buf2[i * 2 + 0] = ((const uint*)s2)[x1]; - buf2[i * 2 + 1] = ((const uint*)s2)[x2]; - } else { - buf1[i * 2 + 0] = fetch(s1, x1); - buf1[i * 2 + 1] = fetch(s1, x2); - buf2[i * 2 + 0] = fetch(s2, x1); - buf2[i * 2 + 1] = fetch(s2, x2); - } + buf1[i * 2 + 0] = fetch1(s1, x1); + buf1[i * 2 + 1] = fetch1(s1, x2); + buf2[i * 2 + 0] = fetch1(s2, x1); + buf2[i * 2 + 1] = fetch1(s2, x2); fx += fdx; fy += fdy; @@ -3294,23 +3206,32 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = { }; static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = { - fetchUntransformed, // Untransformed - fetchUntransformed, // Tiled - fetchTransformed<BlendTransformed>, // Transformed - fetchTransformed<BlendTransformedTiled>, // TransformedTiled - fetchTransformedBilinear<BlendTransformedBilinear>, // Bilinear - fetchTransformedBilinear<BlendTransformedBilinearTiled> // BilinearTiled + fetchUntransformed, // Untransformed + fetchUntransformed, // Tiled + fetchTransformed<BlendTransformed, QPixelLayout::BPPNone>, // Transformed + fetchTransformed<BlendTransformedTiled, QPixelLayout::BPPNone>, // TransformedTiled + fetchTransformedBilinear<BlendTransformedBilinear, QPixelLayout::BPPNone>, // TransformedBilinear + fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPPNone> // TransformedBilinearTiled }; static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = { fetchUntransformedARGB32PM, // Untransformed fetchUntransformedARGB32PM, // Tiled - fetchTransformedARGB32PM<BlendTransformed>, // Transformed - fetchTransformedARGB32PM<BlendTransformedTiled>, // TransformedTiled + fetchTransformed<BlendTransformed, QPixelLayout::BPP32>, // Transformed + fetchTransformed<BlendTransformedTiled, QPixelLayout::BPP32>, // TransformedTiled fetchTransformedBilinearARGB32PM<BlendTransformedBilinear>, // Bilinear fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled> // BilinearTiled }; +static SourceFetchProc sourceFetchAny32[NBlendTypes] = { + fetchUntransformed, // Untransformed + fetchUntransformed, // Tiled + fetchTransformed<BlendTransformed, QPixelLayout::BPP32>, // Transformed + fetchTransformed<BlendTransformedTiled, QPixelLayout::BPP32>, // TransformedTiled + fetchTransformedBilinear<BlendTransformedBilinear, QPixelLayout::BPP32>, // TransformedBilinear + fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP32> // TransformedBilinearTiled +}; + static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = { fetchUntransformed64, // Untransformed fetchUntransformed64, // Tiled @@ -3326,6 +3247,8 @@ static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage: return sourceFetchARGB32PM[blendType]; if (blendType == BlendUntransformed || blendType == BlendTiled) return sourceFetchUntransformed[format]; + if (qPixelLayouts[format].bpp == QPixelLayout::BPP32) + return sourceFetchAny32[blendType]; return sourceFetchGeneric[blendType]; } @@ -4718,8 +4641,10 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; uint buffer[buffer_size]; - int image_width = data->texture.width; - int image_height = data->texture.height; + const int image_x1 = data->texture.x1; + const int image_y1 = data->texture.y1; + const int image_x2 = data->texture.x2 - 1; + const int image_y2 = data->texture.y2 - 1; if (data->fast_matrix) { // The increment pr x in the scanline @@ -4746,8 +4671,8 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData const uint *end = buffer + l; uint *b = buffer; while (b < end) { - int px = qBound(0, x >> 16, image_width - 1); - int py = qBound(0, y >> 16, image_height - 1); + int px = qBound(image_x1, x >> 16, image_x2); + int py = qBound(image_y1, y >> 16, image_y2); *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; x += fdx; @@ -4786,8 +4711,8 @@ static void blend_transformed_argb(int count, const QSpan *spans, void *userData const qreal iw = w == 0 ? 1 : 1 / w; const qreal tx = x * iw; const qreal ty = y * iw; - const int px = qBound(0, int(tx) - (tx < 0), image_width - 1); - const int py = qBound(0, int(ty) - (ty < 0), image_height - 1); + const int px = qBound(image_x1, int(tx) - (tx < 0), image_x2); + const int py = qBound(image_y1, int(ty) - (ty < 0), image_y2); *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; x += fdx; @@ -4819,8 +4744,10 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa } quint16 buffer[buffer_size]; - const int image_width = data->texture.width; - const int image_height = data->texture.height; + const int image_x1 = data->texture.x1; + const int image_y1 = data->texture.y1; + const int image_x2 = data->texture.x2 - 1; + const int image_y2 = data->texture.y2 - 1; if (data->fast_matrix) { // The increment pr x in the scanline @@ -4858,8 +4785,8 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa const quint16 *end = b + l; while (b < end) { - const int px = qBound(0, x >> 16, image_width - 1); - const int py = qBound(0, y >> 16, image_height - 1); + const int px = qBound(image_x1, x >> 16, image_x2); + const int py = qBound(image_y1, y >> 16, image_y2); *b = ((const quint16 *)data->texture.scanLine(py))[px]; ++b; @@ -4917,8 +4844,8 @@ static void blend_transformed_rgb565(int count, const QSpan *spans, void *userDa const qreal tx = x * iw; const qreal ty = y * iw; - const int px = qBound(0, int(tx) - (tx < 0), image_width - 1); - const int py = qBound(0, int(ty) - (ty < 0), image_height - 1); + const int px = qBound(image_x1, int(tx) - (tx < 0), image_x2); + const int py = qBound(image_y1, int(ty) - (ty < 0), image_y2); *b = ((const quint16 *)data->texture.scanLine(py))[px]; ++b; |