From 9b94570fdf085e4979b139a6f8ea3f9bab5a36a7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 28 Dec 2011 17:22:34 -0200 Subject: [PATCH] Add AVX support for the painting and image code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no new routines, this is just the old SSE2 and SSSE3 code compiled in AVX mode, meaning the instructions use the VEX prefix. Change-Id: I79a8bfaf6b30a050618db899f5a3bbc220449f0b Reviewed-by: Samuel Rødal --- src/gui/gui.pro | 12 +++++ src/gui/image/image.pri | 1 + src/gui/image/qimage.cpp | 33 +++++++++---- src/gui/image/qimage_avx.cpp | 57 ++++++++++++++++++++++ src/gui/painting/painting.pri | 3 +- src/gui/painting/qdrawhelper.cpp | 57 ++++++++++++++++++++++ src/gui/painting/qdrawhelper_avx.cpp | 70 +++++++++++++++++++++++++++ src/gui/painting/qdrawhelper_sse2.cpp | 5 ++ src/gui/painting/qdrawhelper_x86_p.h | 19 ++++++++ 9 files changed, 246 insertions(+), 11 deletions(-) create mode 100644 src/gui/image/qimage_avx.cpp create mode 100644 src/gui/painting/qdrawhelper_avx.cpp diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 2d21a7d7b2..3940705b50 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -84,6 +84,18 @@ win32:!contains(QT_CONFIG, directwrite) { silent:ssse3_compiler.commands = @echo compiling[ssse3] ${QMAKE_FILE_IN} && $$ssse3_compiler.commands QMAKE_EXTRA_COMPILERS += ssse3_compiler } + avx { + avx_compiler.commands = $$QMAKE_CXX -c -Winline + avx_compiler.commands += -mavx + avx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + avx_compiler.dependency_type = TYPE_C + avx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} + avx_compiler.input = AVX_SOURCES + avx_compiler.variable_out = OBJECTS + avx_compiler.name = compiling[avx] ${QMAKE_FILE_IN} + silent:avx_compiler.commands = @echo compiling[avx] ${QMAKE_FILE_IN} && $$avx_compiler.commands + QMAKE_EXTRA_COMPILERS += avx_compiler + } iwmmxt { iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline iwmmxt_compiler.commands += -mcpu=iwmmxt diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 6b306ddaad..f29385d0a5 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -77,3 +77,4 @@ contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri) NEON_SOURCES += image/qimage_neon.cpp SSE2_SOURCES += image/qimage_sse2.cpp SSSE3_SOURCES += image/qimage_ssse3.cpp +AVX_SOURCES += image/qimage_avx.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 89060cfbb4..2d70b28923 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3273,19 +3273,32 @@ void qInitImageConversions() Q_UNUSED(features); #ifdef QT_HAVE_SSE2 - if (features & SSE2) { - extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); - inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2; - } +#ifdef QT_HAVE_AVX + if (features & AVX) { + extern bool convert_ARGB_to_ARGB_PM_inplace_avx(QImageData *data, Qt::ImageConversionFlags); + inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_avx; + + extern void convert_RGB888_to_RGB32_avx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); + converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_avx; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_avx; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_avx; + } else #endif + + if (features & SSE2) { + extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); + inplace_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_inplace_sse2; #ifdef QT_HAVE_SSSE3 - if (features & SSSE3) { - extern void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); - converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3; - converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3; - converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3; - } + if (features & SSSE3) { + extern void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); + converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3; + converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3; + } #endif + } +#endif // SSE2 + #ifdef QT_HAVE_NEON if (features & NEON) { extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); diff --git a/src/gui/image/qimage_avx.cpp b/src/gui/image/qimage_avx.cpp new file mode 100644 index 0000000000..f112a46d96 --- /dev/null +++ b/src/gui/image/qimage_avx.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Intel Corporation +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifdef QT_HAVE_AVX + +#ifndef __AVX__ +#error "AVX not enabled in this file, cannot proceed" +#endif + +#define convert_ARGB_to_ARGB_PM_inplace_sse2 convert_ARGB_to_ARGB_PM_inplace_avx +#include "qimage_sse2.cpp" + +#define qt_convert_rgb888_to_rgb32_ssse3 qt_convert_rgb888_to_rgb32_avx +#define convert_RGB888_to_RGB32_ssse3 convert_RGB888_to_RGB32_avx +#include "qimage_ssse3.cpp" + +#endif diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 7a20f35b33..e4b3f5e568 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -91,12 +91,13 @@ SOURCES += \ -if(mmx|3dnow|sse|sse2|iwmmxt) { +if(mmx|3dnow|sse|sse2|iwmmxt|avx) { HEADERS += painting/qdrawhelper_x86_p.h \ painting/qdrawingprimitive_sse2_p.h SSE2_SOURCES += painting/qdrawhelper_sse2.cpp SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp + AVX_SOURCES += painting/qdrawhelper_avx.cpp } NEON_SOURCES += painting/qdrawhelper_neon.cpp diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index c21cc61ec5..23a1853314 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5805,6 +5805,24 @@ void qInitDrawhelperAsm() const uint features = qDetectCPUFeatures(); if (false) { +#ifdef QT_HAVE_AVX + } else if (features & AVX) { + qt_memfill32 = qt_memfill32_avx; + qt_memfill16 = qt_memfill16_avx; + qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_avx; + qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_avx; + qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_avx; + qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_avx; + + extern void qt_scale_image_argb32_on_argb32_avx(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + const QRectF &targetRect, + const QRectF &sourceRect, + const QRect &clip, + int const_alpha); + qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_avx; + qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_avx; +#endif #ifdef QT_HAVE_SSE2 } else if (features & SSE2) { qt_memfill32 = qt_memfill32_sse2; @@ -5859,12 +5877,51 @@ void qInitDrawhelperAsm() } #endif // SSSE3 +#ifdef QT_HAVE_AVX + if (features & AVX) { + extern void qt_blend_rgb32_on_rgb32_avx(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + extern void qt_blend_argb32_on_argb32_avx(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); + + qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_avx; + qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx; + qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_avx; + + extern const uint * QT_FASTCALL qt_fetch_radial_gradient_avx(uint *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length); + + qt_fetch_radial_gradient = qt_fetch_radial_gradient_avx; + } +#endif // AVX + #endif // SSE2 #ifdef QT_HAVE_SSE2 if (features & SSE2) { functionForModeAsm = qt_functionForMode_SSE2; functionForModeSolidAsm = qt_functionForModeSolid_SSE2; + } +#endif +#ifdef QT_HAVE_AVX + if (features & AVX) { + extern void QT_FASTCALL comp_func_SourceOver_avx(uint *destPixels, + const uint *srcPixels, + int length, + uint const_alpha); + extern void QT_FASTCALL comp_func_solid_SourceOver_avx(uint *destPixels, int length, uint color, uint const_alpha); + extern void QT_FASTCALL comp_func_Plus_avx(uint *dst, const uint *src, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_Source_avx(uint *dst, const uint *src, int length, uint const_alpha); + + functionForModeAsm[0] = comp_func_SourceOver_avx; + functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_avx; + functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_avx; + functionForModeSolidAsm[0] = comp_func_solid_SourceOver_avx; } #endif // SSE2 diff --git a/src/gui/painting/qdrawhelper_avx.cpp b/src/gui/painting/qdrawhelper_avx.cpp new file mode 100644 index 0000000000..28ba5f8aa3 --- /dev/null +++ b/src/gui/painting/qdrawhelper_avx.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Intel Corporation +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifdef QT_HAVE_AVX +#define QDRAWHELPER_AVX + +#ifndef __AVX__ +#error "AVX not enabled in this file, cannot proceed" +#endif + +#define qt_blend_argb32_on_argb32_ssse3 qt_blend_argb32_on_argb32_avx +#include "qdrawhelper_ssse3.cpp" + +//#define qt_blend_argb32_on_argb32_sse2 qt_blend_argb32_on_argb32_avx +#define qt_blend_rgb32_on_rgb32_sse2 qt_blend_rgb32_on_rgb32_avx +#define comp_func_SourceOver_sse2 comp_func_SourceOver_avx +#define comp_func_Plus_sse2 comp_func_Plus_avx +#define comp_func_Source_sse2 comp_func_Source_avx +#define comp_func_solid_SourceOver_sse2 comp_func_solid_SourceOver_avx +#define qt_memfill32_sse2 qt_memfill32_avx +#define qt_memfill16_sse2 qt_memfill16_avx +#define qt_bitmapblit32_sse2 qt_bitmapblit32_avx +#define qt_bitmapblit16_sse2 qt_bitmapblit16_avx +#define QSimdSse2 QSimdAvx +#define qt_fetch_radial_gradient_sse2 qt_fetch_radial_gradient_avx +#define qt_scale_image_argb32_on_argb32_sse2 qt_scale_image_argb32_on_argb32_avx + +#include "qdrawhelper_sse2.cpp" + +#endif diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 2c87aabe93..e44116570d 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +#ifndef QDRAWHELPER_AVX +// in AVX mode, we'll use the SSSE3 code void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, @@ -83,6 +85,7 @@ void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, } } } +#endif // qblendfunctions.cpp void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, @@ -310,6 +313,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, u } } +#ifndef QDRAWHELPER_AVX CompositionFunctionSolid qt_functionForModeSolid_SSE2[numCompositionFunctions] = { comp_func_solid_SourceOver_sse2, comp_func_solid_DestinationOver, @@ -381,6 +385,7 @@ CompositionFunction qt_functionForMode_SSE2[numCompositionFunctions] = { rasterop_NotSourceAndDestination, rasterop_SourceAndNotDestination }; +#endif void qt_memfill16_sse2(quint16 *dest, quint16 value, int count) { diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 93abaf4fff..eb434e5fda 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -79,6 +79,25 @@ extern CompositionFunction qt_functionForMode_SSE2[]; extern CompositionFunctionSolid qt_functionForModeSolid_SSE2[]; #endif // QT_HAVE_SSE2 +#ifdef QT_HAVE_AVX +void qt_memfill32_avx(quint32 *dest, quint32 value, int count); +void qt_memfill16_avx(quint16 *dest, quint16 value, int count); +void qt_bitmapblit32_avx(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); +void qt_bitmapblit16_avx(QRasterBuffer *rasterBuffer, int x, int y, + quint32 color, + const uchar *src, int width, int height, int stride); +void qt_blend_argb32_on_argb32_avx(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); +void qt_blend_rgb32_on_rgb32_avx(uchar *destPixels, int dbpl, + const uchar *srcPixels, int sbpl, + int w, int h, + int const_alpha); +#endif // QT_HAVE_AVX + #ifdef QT_HAVE_IWMMXT void qt_blend_color_argb_iwmmxt(int count, const QSpan *spans, void *userData);