diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-08-03 01:00:16 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2018-08-07 17:44:51 +0200 |
commit | 053e7cce79d4bef99ec85101b0d22bbb171072c5 (patch) | |
tree | c2059e82cccdea1fd0024c5942d1a834c28d39da /src/gui/painting | |
parent | a420d02538d28854914a6978c9637a0ddd652146 (diff) | |
parent | f271dd8f960ad9f61697dfa57b26c4071441cadc (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts:
.qmake.conf
src/corelib/doc/src/objectmodel/signalsandslots.qdoc
src/plugins/platforms/cocoa/qcocoamenuloader.mm
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection.h
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/plugins/platforms/xcb/qxcbwindow.cpp
tests/auto/gui/image/qimage/tst_qimage.cpp
Done-with: Gatis Paeglis <gatis.paeglis@qt.io>
Change-Id: I9bd24ee9b00d4f26c8f344ce3970aa6e93935ff5
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 61 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 119 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster_p.h | 3 |
3 files changed, 181 insertions, 2 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 235bba7206..1110f951a9 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -841,6 +841,53 @@ static inline void qConvertARGB32PMToARGB64PM_sse2(QRgba64 *buffer, const uint * *buffer++ = QRgba64::fromArgb32(s); } } +#elif defined(__ARM_NEON__) +template<bool RGBA, bool maskAlpha> +static inline void qConvertARGB32PMToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count) +{ + if (count <= 0) + return; + + const uint32x4_t amask = vdupq_n_u32(0xff000000); +#if defined(Q_PROCESSOR_ARM_64) + const uint8x16_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15}; +#else + const uint8x8_t rgbaMask = { 2, 1, 0, 3, 6, 5, 4, 7 }; +#endif + int i = 0; + for (; i < count-3; i += 4) { + uint32x4_t vs32 = vld1q_u32(src); + src += 4; + if (maskAlpha) + vs32 = vorrq_u32(vs32, amask); + uint8x16_t vs8 = vreinterpretq_u8_u32(vs32); + if (!RGBA) { +#if defined(Q_PROCESSOR_ARM_64) + vs8 = vqtbl1q_u8(vs8, rgbaMask); +#else + // no vqtbl1q_u8 + const uint8x8_t vlo = vtbl1_u8(vget_low_u8(vs8), rgbaMask); + const uint8x8_t vhi = vtbl1_u8(vget_high_u8(vs8), rgbaMask); + vs8 = vcombine_u8(vlo, vhi); +#endif + } + uint8x16x2_t v = vzipq_u8(vs8, vs8); + + vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u8(v.val[0])); + buffer += 2; + vst1q_u16((uint16_t *)buffer, vreinterpretq_u16_u8(v.val[1])); + buffer += 2; + } + + SIMD_EPILOGUE(i, count, 3) { + uint s = *src++; + if (maskAlpha) + s = s | 0xff000000; + if (RGBA) + s = RGBA2ARGB(s); + *buffer++ = QRgba64::fromArgb32(s); + } +} #endif static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uint *src, int count, @@ -848,6 +895,8 @@ static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uin { #ifdef __SSE2__ qConvertARGB32PMToARGB64PM_sse2<false, true>(buffer, src, count); +#elif defined(__ARM_NEON__) + qConvertARGB32PMToRGBA64PM_neon<false, true>(buffer, src, count); #else for (int i = 0; i < count; ++i) buffer[i] = QRgba64::fromArgb32(0xff000000 | src[i]); @@ -862,6 +911,10 @@ static const QRgba64 *QT_FASTCALL convertARGB32ToARGB64PM(QRgba64 *buffer, const qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count); for (int i = 0; i < count; ++i) buffer[i] = buffer[i].premultiplied(); +#elif defined(__ARM_NEON__) + qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count); + for (int i = 0; i < count; ++i) + buffer[i] = buffer[i].premultiplied(); #else for (int i = 0; i < count; ++i) buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied(); @@ -874,6 +927,8 @@ static const QRgba64 *QT_FASTCALL convertARGB32PMToARGB64PM(QRgba64 *buffer, con { #ifdef __SSE2__ qConvertARGB32PMToARGB64PM_sse2<false, false>(buffer, src, count); +#elif defined(__ARM_NEON__) + qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count); #else for (int i = 0; i < count; ++i) buffer[i] = QRgba64::fromArgb32(src[i]); @@ -888,6 +943,10 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888ToARGB64PM(QRgba64 *buffer, con qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count); for (int i = 0; i < count; ++i) buffer[i] = buffer[i].premultiplied(); +#elif defined(__ARM_NEON__) + qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count); + for (int i = 0; i < count; ++i) + buffer[i] = buffer[i].premultiplied(); #else for (int i = 0; i < count; ++i) buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])).premultiplied(); @@ -900,6 +959,8 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888PMToARGB64PM(QRgba64 *buffer, c { #ifdef __SSE2__ qConvertARGB32PMToARGB64PM_sse2<true, false>(buffer, src, count); +#elif defined(__ARM_NEON__) + qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count); #else for (int i = 0; i < count; ++i) buffer[i] = QRgba64::fromArgb32(RGBA2ARGB(src[i])); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index e0dd789dfd..7caaf3a8fa 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1056,6 +1056,77 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, alpha); } +void QRasterPaintEnginePrivate::blitImage(const QPointF &pt, + const QImage &img, + const QRect &clip, + const QRect &sr) +{ + if (!clip.isValid()) + return; + + Q_ASSERT(img.depth() >= 8); + + qsizetype srcBPL = img.bytesPerLine(); + const uchar *srcBits = img.bits(); + int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit.. + int iw = img.width(); + int ih = img.height(); + + if (!sr.isEmpty()) { + iw = sr.width(); + ih = sr.height(); + // Adjust the image according to the source offset... + srcBits += ((sr.y() * srcBPL) + sr.x() * srcSize); + } + + // adapt the x parameters + int x = qRound(pt.x()); + int cx1 = clip.x(); + int cx2 = clip.x() + clip.width(); + if (x < cx1) { + int d = cx1 - x; + srcBits += srcSize * d; + iw -= d; + x = cx1; + } + if (x + iw > cx2) { + int d = x + iw - cx2; + iw -= d; + } + if (iw <= 0) + return; + + // adapt the y paremeters... + int cy1 = clip.y(); + int cy2 = clip.y() + clip.height(); + int y = qRound(pt.y()); + if (y < cy1) { + int d = cy1 - y; + srcBits += srcBPL * d; + ih -= d; + y = cy1; + } + if (y + ih > cy2) { + int d = y + ih - cy2; + ih -= d; + } + if (ih <= 0) + return; + + // blit.. + int dstSize = rasterBuffer->bytesPerPixel(); + qsizetype dstBPL = rasterBuffer->bytesPerLine(); + const uint *src = (const uint *) srcBits; + uint *dst = reinterpret_cast<uint *>(rasterBuffer->buffer() + x * dstSize + y * dstBPL); + + const int len = iw * (qt_depthForFormat(rasterBuffer->format) >> 3); + for (int y = 0; y < ih; ++y) { + memcpy(dst, src, len); + dst = (quint32 *)(((uchar *) dst) + dstBPL); + src = (const quint32 *)(((const uchar *) src) + srcBPL); + } +} + void QRasterPaintEnginePrivate::systemStateChanged() { @@ -2160,7 +2231,15 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img) const QClipData *clip = d->clip(); QPointF pt(p.x() + s->matrix.dx(), p.y() + s->matrix.dy()); - if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { + if (!clip) { + d->blitImage(pt, img, d->deviceRect); + return; + } else if (clip->hasRectClip) { + d->blitImage(pt, img, clip->clipRect); + return; + } + } else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { if (!clip) { @@ -2445,7 +2524,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe fillPath(path, &d->image_filler_xform); s->matrix = m; } else { - if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { + if (d->canUseImageBlitting(d->rasterBuffer->compositionMode, img)) { + QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); + if (!clip) { + d->blitImage(pt, img, d->deviceRect, sr.toRect()); + return; + } else if (clip->hasRectClip) { + d->blitImage(pt, img, clip->clipRect, sr.toRect()); + return; + } + } else if (d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()]; if (func) { QPointF pt(r.x() + s->matrix.dx(), r.y() + s->matrix.dy()); @@ -3668,6 +3756,33 @@ bool QRasterPaintEnginePrivate::canUseFastImageBlending(QPainter::CompositionMod && !image.hasAlphaChannel())); } +bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const +{ + Q_Q(const QRasterPaintEngine); + const QRasterPaintEngineState *s = q->state(); + + if (!s->flags.fast_images || s->intOpacity != 256 || qt_depthForFormat(rasterBuffer->format) < 8) + return false; + + QImage::Format dFormat = rasterBuffer->format; + QImage::Format sFormat = image.format(); + // Formats must match or source format must be a subset of destination format + if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) { + if ((sFormat == QImage::Format_RGB32 && dFormat == QImage::Format_ARGB32) + || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888)) + sFormat = dFormat; + else + sFormat = qt_maybeAlphaVersionWithSameDepth(sFormat); // this returns premul formats + } + if (dFormat != sFormat) + return false; + + return s->matrix.type() <= QTransform::TxTranslate + && (mode == QPainter::CompositionMode_Source + || (mode == QPainter::CompositionMode_SourceOver + && !image.hasAlphaChannel())); +} + QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) { Q_ASSERT(image.depth() == 1); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 8c6f668d9d..14eddf07b1 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -291,6 +291,8 @@ public: void drawImage(const QPointF &pt, const QImage &img, SrcOverBlendFunc func, const QRect &clip, int alpha, const QRect &sr = QRect()); + void blitImage(const QPointF &pt, const QImage &img, + const QRect &clip, const QRect &sr = QRect()); QTransform brushMatrix() const { Q_Q(const QRasterPaintEngine); @@ -313,6 +315,7 @@ public: void recalculateFastImages(); bool canUseFastImageBlending(QPainter::CompositionMode mode, const QImage &image) const; + bool canUseImageBlitting(QPainter::CompositionMode mode, const QImage &image) const; QPaintDevice *device; QScopedPointer<QOutlineMapper> outlineMapper; |