From 7037539f385d05725ccf863167db69d771daa8c3 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 25 Aug 2016 14:38:38 +0200 Subject: Optimize the simple QImage flip used by OpenGL The vertical mirror is simple enough it can be done by memcpy most of the time, and is commonly used when bridging raster and OpenGL. This patch adds a simple optimized function for QImage flipping. Change-Id: I83a0192fc150576dcf573895cdaecb17b0ed72a5 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/image/qimage.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index e1da0ffffc..8bbcfa612d 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3014,6 +3014,37 @@ template inline void do_mirror_data(QImageData *dst, QImageData *src, } } +inline void do_flip(QImageData *dst, QImageData *src, int w, int h, int depth) +{ + const int data_bytes_per_line = w * (depth / 8); + if (dst == src) { + uint *srcPtr = reinterpret_cast(src->data); + uint *dstPtr = reinterpret_cast(dst->data + (h - 1) * dst->bytes_per_line); + h = h / 2; + const int uint_per_line = (data_bytes_per_line + 3) >> 2; // bytes per line must be a multiple of 4 + for (int y = 0; y < h; ++y) { + // This is auto-vectorized, no need for SSE2 or NEON versions: + for (int x = 0; x < uint_per_line; x++) { + const uint d = dstPtr[x]; + const uint s = srcPtr[x]; + dstPtr[x] = s; + srcPtr[x] = d; + } + srcPtr += src->bytes_per_line >> 2; + dstPtr -= dst->bytes_per_line >> 2; + } + + } else { + const uchar *srcPtr = src->data; + uchar *dstPtr = dst->data + (h - 1) * dst->bytes_per_line; + for (int y = 0; y < h; ++y) { + memcpy(dstPtr, srcPtr, data_bytes_per_line); + srcPtr += src->bytes_per_line; + dstPtr -= dst->bytes_per_line; + } + } +} + inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical) { Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth); @@ -3026,6 +3057,12 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve depth = 8; } + if (vertical && !horizontal) { + // This one is simple and common, so do it a little more optimized + do_flip(dst, src, w, h, depth); + return; + } + int dstX0 = 0, dstXIncr = 1; int dstY0 = 0, dstYIncr = 1; if (horizontal) { -- cgit v1.2.3