diff options
author | Benjamin Poulain <benjamin.poulain@nokia.com> | 2010-07-23 14:14:49 (GMT) |
---|---|---|
committer | Benjamin Poulain <benjamin.poulain@nokia.com> | 2010-07-26 10:40:00 (GMT) |
commit | 90642dd2b6b14c39cc6178f1161331895809b342 (patch) | |
tree | 47cebd733363e9f8560cb2f9909f816dbe8a1def /tests | |
parent | 38d8826503385f249cfd4d35382a79252de85873 (diff) | |
download | Qt-90642dd2b6b14c39cc6178f1161331895809b342.zip Qt-90642dd2b6b14c39cc6178f1161331895809b342.tar.gz Qt-90642dd2b6b14c39cc6178f1161331895809b342.tar.bz2 |
Use SSSE3 to convert from RGB888 to RGB32
Converting from RGB encoded on 24bits to RGB encoded on 32 bits is
quite inefficient.
This type of conversion is common for some image format.
The patch implement the conversion with SSSE3. This reduce by 3 the
number of instructions, pushing the bottleneck to memory bandwidth.
On Atom N450, the new benchmark is 40% faster for scanlines of
2000 pixels, 30% faster for scanlines of 32 pixels, and 15% slower
for small images (3 and 8px).
Reviewed-by: Olivier Goffart
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qimage/tst_qimage.cpp | 22 | ||||
-rw-r--r-- | tests/benchmarks/gui/image/image.pro | 1 | ||||
-rw-r--r-- | tests/benchmarks/gui/image/qimageconversion/qimageconversion.pro | 10 | ||||
-rw-r--r-- | tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp | 108 |
4 files changed, 141 insertions, 0 deletions
diff --git a/tests/auto/qimage/tst_qimage.cpp b/tests/auto/qimage/tst_qimage.cpp index 5052114..1330d96 100644 --- a/tests/auto/qimage/tst_qimage.cpp +++ b/tests/auto/qimage/tst_qimage.cpp @@ -83,6 +83,8 @@ private slots: void convertToFormat_data(); void convertToFormat(); + void convertToFormatRgb888ToRGB32(); + void createAlphaMask_data(); void createAlphaMask(); #ifndef QT_NO_IMAGE_HEURISTIC_MASK @@ -799,6 +801,26 @@ void tst_QImage::convertToFormat() QFile::remove(QLatin1String("expected2.xpm")); } +void tst_QImage::convertToFormatRgb888ToRGB32() +{ + // 545 so width % 4 != 0. This ensure there is padding at the end of the scanlines + const int height = 545; + const int width = 545; + QImage source(width, height, QImage::Format_RGB888); + for (int y = 0; y < height; ++y) { + uchar *srcPixels = source.scanLine(y); + for (int x = 0; x < width * 3; ++x) + srcPixels[x] = x; + } + + QImage rgb32Image = source.convertToFormat(QImage::Format_RGB888); + QCOMPARE(rgb32Image.format(), QImage::Format_RGB888); + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) + QCOMPARE(rgb32Image.pixel(x, y), source.pixel(x, y)); + } +} + void tst_QImage::createAlphaMask_data() { QTest::addColumn<int>("x"); diff --git a/tests/benchmarks/gui/image/image.pro b/tests/benchmarks/gui/image/image.pro index 3094e72..a8c6732 100644 --- a/tests/benchmarks/gui/image/image.pro +++ b/tests/benchmarks/gui/image/image.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS = \ blendbench \ + qimageconversion \ qimagereader \ qpixmap \ qpixmapcache diff --git a/tests/benchmarks/gui/image/qimageconversion/qimageconversion.pro b/tests/benchmarks/gui/image/qimageconversion/qimageconversion.pro new file mode 100644 index 0000000..ec50d98 --- /dev/null +++ b/tests/benchmarks/gui/image/qimageconversion/qimageconversion.pro @@ -0,0 +1,10 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_imageConversion + +SOURCES += tst_qimageconversion.cpp + +!contains(QT_CONFIG, no-gif):DEFINES += QTEST_HAVE_GIF +!contains(QT_CONFIG, no-jpeg):DEFINES += QTEST_HAVE_JPEG +!contains(QT_CONFIG, no-mng):DEFINES += QTEST_HAVE_MNG +!contains(QT_CONFIG, no-tiff):DEFINES += QTEST_HAVE_TIFF diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp new file mode 100644 index 0000000..1c76d46 --- /dev/null +++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QImage> + +Q_DECLARE_METATYPE(QImage) + +class tst_QImageConversion : public QObject +{ + Q_OBJECT +private slots: + void convertRgb888ToRGB32_data(); + void convertRgb888ToRGB32(); + +private: + QImage generateImageRgb888(int width, int height); +}; + +void tst_QImageConversion::convertRgb888ToRGB32_data() +{ + QTest::addColumn<QImage>("inputImage"); + // height = 5000 to get interesting timing. + + // 3 pixels wide -> smaller than regular vector of 128bits + QTest::newRow("width: 3px; height: 5000px;") << generateImageRgb888(3, 5000); + + // 8 pixels wide -> potential for 2 vectors + QTest::newRow("width: 8px; height: 5000px;") << generateImageRgb888(3, 5000); + + // 16 pixels, minimum for the SSSE3 implementation + QTest::newRow("width: 16px; height: 5000px;") << generateImageRgb888(16, 5000); + + // 50 pixels, more realistic use case + QTest::newRow("width: 50px; height: 5000px;") << generateImageRgb888(50, 5000); + + // 2000 pixels -> typical values for pictures + QTest::newRow("width: 2000px; height: 5000px;") << generateImageRgb888(2000, 5000); +} + +void tst_QImageConversion::convertRgb888ToRGB32() +{ + QFETCH(QImage, inputImage); + + QBENCHMARK { + volatile QImage output = inputImage.convertToFormat(QImage::Format_RGB32); + // we need the volatile and the following to make sure the compiler does not do + // anything stupid :) + (void)output; + } +} + +/* + Fill a RGB888 image with "random" pixel values. + */ +QImage tst_QImageConversion::generateImageRgb888(int width, int height) +{ + QImage image(width, height, QImage::Format_RGB888); + const int byteWidth = width * 3; + + for (int y = 0; y < image.height(); ++y) { + uchar *scanline = image.scanLine(y); + for (int x = 0; x < byteWidth; ++x) + scanline[x] = x ^ y; + } + return image; +} + +QTEST_MAIN(tst_QImageConversion) +#include "tst_qimageconversion.moc" |