












本文档旨在指导开发者如何在 Windows 操作系统上,为面向 LoongArch64 架构的 OpenHarmony 4.1 (API 11) 系统编译 Qt 5.15.12 版本的软件开发工具包 (SDK)。
v5.15.12-lts-lgplloongarch64Alpha_v6 (或更新版本)重要提示: OpenHarmony 社区提供的
Alpha_v6补丁版本仅支持 OpenHarmony API 11(OHOS 4.1), 兼容OpenHarmony API 12(OHOS 5.0),不再兼容早期的 API 9 和 API 10。同时,由于 Qt 5.12.12 版本存在较多问题,已停止维护,请务必使用 Qt 5.15.12。
在开始编译之前,请确保您的 Windows 系统已安装并配置好以下工具。您可以使用 winget 包管理器快速安装。
打开 PowerShell 或 CMD 窗口,执行以下命令:
# 安装 LLVM-MinGW 工具链 (UCRT 版本),**注意要在环境变量里将其安装的 PATH 移到最前,保证调用的工具链是 LLVM-MinGW**
winget install MartinStorsjo.LLVM-MinGW.UCRT
# 安装 Strawberry Perl
winget install StrawberryPerl.StrawberryPerl
# 安装 Python 3.11
winget install Python.Python.3.11
# 安装 Git
winget install Git.Git
除此之外,您还需要:
C:\windows-ohos-sdk)。C:\src),然后克隆 Qt5 的官方源码仓库。
git clone https://github.com/qt/qt5
cd qt5
v5.15.12-lts-lgpl 长期支持版。
git checkout -b v5.15.12-lts-lgpl v5.15.12-lts-lgpl
git submodule update --init
OpenHarmony SIG 团队提供了适配 Qt 的补丁,需要手动应用到源码中。
请下载 Alpha_v6 或更高版本的 v5.15.12 对应的补丁包,并解压到本地目录(例如 C:\src\ohos-qt-patches)。
git apply 命令应用补丁。请将 <您的补丁路径> 替换为您实际的补丁文件存放路径。
# 假设 Qt 源码位于 C:\src\qt5,补丁位于 C:\src\ohos-qt-patches
# 注意:请根据您的实际路径进行调整
# 1. 为 qtbase 打补丁
cd C:\src\qt5\qtbase
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtbase.patch
# 2. 为 qt3d 打补丁
cd C:\src\qt5\qt3d
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qt3d.patch
# 3. 为 qtconnectivity 打补丁
cd C:\src\qt5\qtconnectivity
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtconnectivity.patch
# 4. 为 qtdeclarative 打补丁
cd C:\src\qt5\qtdeclarative
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtdeclarative.patch
# 5. 为 qtmultimedia 打补丁
cd C:\src\qt5\qtmultimedia
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtmultimedia.patch
# 6. 为 qtquickcontrols 打补丁
cd C:\src\qt5\qtquickcontrols
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtquickcontrols.patch
# 7. 为 qtsensors 打补丁
cd C:\src\qt5\qtsensors
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtsensors.patch
# 8. 为 qtwebview 打补丁
cd C:\src\qt5\qtwebview
git apply C:\src\ohos-qt-patches\patch\v5.15.12\qtwebview.patch
应用完所有补丁后,返回 qt5 根目录。
diff --git a/mkspecs/common/oh-base-head.conf b/mkspecs/common/oh-base-head.conf
index d7be2121374..bb4a955e31e 100644
--- a/mkspecs/common/oh-base-head.conf
+++ b/mkspecs/common/oh-base-head.conf
@@ -6,6 +6,7 @@ isEmpty(NDK_TOOLCHAIN_PREFIX) {
equals(OHOS_ARCH, arm64-v8a): NDK_TOOLCHAIN_PREFIX = aarch64-linux-ohos
else: equals(OHOS_ARCH, armeabi-v7a): NDK_TOOLCHAIN_PREFIX = arm-linux-ohos
else: equals(OHOS_ARCH, x86_64): NDK_TOOLCHAIN_PREFIX = x86_64-linux-ohos
+ else: equals(OHOS_ARCH, loongarch64): NDK_TOOLCHAIN_PREFIX = loongarch64-linux-ohos
else: NDK_TOOLCHAIN_PREFIX = arm-linux-ohos
}
diff --git a/mkspecs/common/oh-base-tail.conf b/mkspecs/common/oh-base-tail.conf
index 4039af1e790..1f43ed9b507 100644
--- a/mkspecs/common/oh-base-tail.conf
+++ b/mkspecs/common/oh-base-tail.conf
@@ -4,6 +4,8 @@ else: equals(OHOS_ARCH, arm64-v8a): \
QMAKE_CFLAGS += -march=armv8a -msoft-float -mfpu=vfp -fno-builtin-memmove
else: equals(OHOS_ARCH, x86_64): \
QMAKE_CFLAGS += -march=x86_64
+else: equals(OHOS_ARCH, loongarch64): \
+ QMAKE_CFLAGS += -march=loongarch64
else: \
QMAKE_CFLAGS += -march=armv7a -msoft-float -mfpu=vfp -fno-builtin-memmove
diff --git a/mkspecs/oh-clang/qmake.conf b/mkspecs/oh-clang/qmake.conf
index 5bfd38b4f5c..57a1f859b7a 100644
--- a/mkspecs/oh-clang/qmake.conf
+++ b/mkspecs/oh-clang/qmake.conf
@@ -20,6 +20,8 @@ else:equals(OHOS_ARCH,arm64-v8a): \
QMAKE_CFLAGS += -target aarch64-linux-ohos
else:equals(OHOS_ARCH,x86-64): \
QMAKE_CFLAGS += -target x86_64-linux-ohos
+else:equals(OHOS_ARCH,loongarch64): \
+ QMAKE_CFLAGS += -target loongarch64-linux-ohos
#QMAKE_CFLAGS+=--gcc-toolchain=$$NDK_LLVM_PATH
QMAKE_LINK += -Wl,--exclude-libs,$$shell_path($$SDK_ROOT/native/llvm/lib/$$NDK_TOOLCHAIN_PREFIX/libunwind.a)
diff --git a/src/3rdparty/double-conversion/include/double-conversion/utils.h b/src/3rdparty/double-conversion/include/double-conversion/utils.h
index 70e697ca005..46293d3d58b 100644
--- a/src/3rdparty/double-conversion/include/double-conversion/utils.h
+++ b/src/3rdparty/double-conversion/include/double-conversion/utils.h
@@ -101,6 +101,7 @@ int main(int argc, char** argv) {
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\
defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
defined(__riscv) || \
+ defined(__loongarch64) || \
defined(__or1k__) || defined(__arc__) || \
defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp
index 1d00b7f5a52..cbea45ee480 100644
--- a/src/corelib/global/archdetect.cpp
+++ b/src/corelib/global/archdetect.cpp
@@ -83,6 +83,8 @@
# define ARCH_PROCESSOR "sparcv9"
#elif defined(Q_PROCESSOR_SPARC)
# define ARCH_PROCESSOR "sparc"
+#elif defined(Q_PROCESSOR_LOONGARCH_64)
+# define ARCH_PROCESSOR "loongarch64"
#else
# define ARCH_PROCESSOR "unknown"
#endif
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h
index 8d657208503..a9f41381513 100644
--- a/src/corelib/global/qprocessordetection.h
+++ b/src/corelib/global/qprocessordetection.h
@@ -223,6 +223,20 @@
# define Q_PROCESSOR_WORDSIZE 8
// Q_BYTE_ORDER not defined, use endianness auto-detection
+/*
+ LoongArch family
+
+ LoongArch is bi-endian, use endianness auto-detection implemented below.
+*/
+#elif defined(__loongarch__)
+# define Q_PROCESSOR_LOONGARCH
+# if __loongarch_grlen == 64
+# define Q_PROCESSOR_LOONGARCH_64
+# else
+# define Q_PROCESSOR_LOONGARCH_32
+# endif
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+
/*
MIPS family, known revisions: I, II, III, IV, 32, 64
diff --git a/src/plugins/platforms/openharmony/qopenharmonymain.cpp b/src/plugins/platforms/openharmony/qopenharmonymain.cpp
index 18becb238fc..9d3b44ee5c4 100644
--- a/src/plugins/platforms/openharmony/qopenharmonymain.cpp
+++ b/src/plugins/platforms/openharmony/qopenharmonymain.cpp
@@ -112,6 +112,8 @@ static napi_value startQtApplication(napi_env env, napi_callback_info info)
QByteArray libDir = bundle + "/libs/arm64";
#elif defined(Q_PROCESSOR_ARM_32)
QByteArray libDir = bundle + "/libs/arm";
+#elif defined(Q_PROCESSOR_LOONGARCH_64)
+ QByteArray libDir = bundle + "/libs/loongarch64";
#endif
QByteArrayList qmls = {bundle + "/entry/resources/rawfile"};
保存上述 diff 为 loongarch_support.patch
cd C:\src\qt5\qtbase
git apply loongarch_support.patch
diff --git a/configure.json b/configure.json
index 4763ff645f0..e6f85f9199a 100644
--- a/configure.json
+++ b/configure.json
@@ -96,6 +96,9 @@
"ltcg": "boolean",
"make": { "type": "addString", "values": [ "examples", "libs", "tests", "tools" ] },
"make-tool": "string",
+
+ "lsx": "boolean",
+ "lasx": "boolean",
"mips_dsp": "boolean",
"mips_dspr2": "boolean",
"mp": { "type": "boolean", "name": "msvc_mp" },
@@ -607,6 +610,14 @@
"type": "x86SimdAlways",
"test": "x86_simd"
},
+ "lsx": {
+ "label": "LSX instructions",
+ "type": "LoongArchSimd"
+ },
+ "lasx": {
+ "label": "LASX instructions",
+ "type": "LoongArchSimd"
+ },
"posix_fallocate": {
"label": "POSIX fallocate()",
"type": "compile",
@@ -1082,6 +1093,22 @@
"condition": "tests.signaling_nan",
"output": [ "publicFeature" ]
},
+ "lsx": {
+ "label": "LSX",
+ "condition": "(arch.loongarch64 || arch.loongarch) && tests.lsx",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_LSX", "value": 1 }
+ ]
+ },
+ "lasx": {
+ "label": "LASX",
+ "condition": "(arch.loongarch64 || arch.loongarch) && tests.lasx",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_LASX", "value": 1 }
+ ]
+ },
"sse2": {
"label": "SSE2",
"condition": "(arch.i386 || arch.x86_64) && tests.sse2",
@@ -1646,7 +1673,18 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"type": "feature",
"args": "mips_dspr2",
"condition": "arch.mips"
+ },
+ {
+ "type": "feature",
+ "args": "lsx",
+ "condition": "arch.loongarch || arch.loongarch64"
+ },
+ {
+ "type": "feature",
+ "args": "lasx",
+ "condition": "arch.loongarch || arch.loongarch64"
}
+
]
},
{
diff --git a/configure.pri b/configure.pri
index 365a16403eb..fe86fe458cf 100644
--- a/configure.pri
+++ b/configure.pri
@@ -445,6 +445,13 @@ defineTest(qtConfTest_x86Simd) {
qtConfTest_compile($${1})
}
+defineTest(qtConfTest_LoongArchSimd) {
+ simd = $$section(1, ".", -1) # last component
+ $${1}.args = CONFIG+=add_cflags DEFINES+=NO_ATTRIBUTE SIMD=$$simd
+ $${1}.test = loongarch_simd
+ qtConfTest_compile($${1})
+}
+
defineTest(qtConfTest_x86SimdAlways) {
configs =
fpfx = $${currentConfig}.features
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index fa65c1dd371..84b8d4852dd 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -119,6 +119,8 @@ QMAKE_CFLAGS_VAES += -mvaes
QMAKE_CFLAGS_NEON += -mfpu=neon
QMAKE_CFLAGS_MIPS_DSP += -mdsp
QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2
+QMAKE_CFLAGS_LSX += -mlsx
+QMAKE_CFLAGS_LASX += -mlasx
# -march=haswell is supported as of GCC 4.9 and Clang 3.6
QMAKE_CFLAGS_ARCH_HASWELL = -march=core-avx2
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index 8e041297d2f..a825fdd4a6f 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -146,6 +146,8 @@ addSimdCompiler(rdseed)
addSimdCompiler(neon)
addSimdCompiler(mips_dsp)
addSimdCompiler(mips_dspr2)
+addSimdCompiler(lsx)
+addSimdCompiler(lasx)
# Haswell sub-architecture
defineTest(addSimdArch) {
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 798ac93ad24..c016fa5bec8 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -109,6 +109,19 @@ static const char features_string[] =
" dspr2\0"
"\0";
+static const int features_indices[] = {
+ 0, 5
+};
+#elif defined(Q_PROCESSOR_LOONGARCH)
+/* Data:
+ lsx
+ lasx
+*/
+static const char features_string[] =
+ " lsx\0"
+ " lasx\0"
+ "\0";
+
static const int features_indices[] = {
0, 5
};
@@ -183,6 +196,28 @@ static inline quint64 detectProcessorFeatures()
return features;
}
+#elif defined(Q_PROCESSOR_LOONGARCH)
+/* have to supply these defines for glibc 2.37- and musl */
+#ifndef HWCAP_LOONGARCH_LSX
+#define HWCAP_LOONGARCH_LSX (1 << 4)
+#endif
+#ifndef HWCAP_LOONGARCH_LASX
+#define HWCAP_LOONGARCH_LASX (1 << 5)
+#endif
+
+ #include <sys/auxv.h>
+static inline quint64 detectProcessorFeatures()
+{
+ quint64 features = 0;
+ quint64 hwcap = getauxval(AT_HWCAP);
+
+ if (hwcap & HWCAP_LOONGARCH_LSX)
+ features |= CpuFeatureLSX;
+ if (hwcap & HWCAP_LOONGARCH_LASX)
+ features |= CpuFeatureLASX;
+ return features;
+}
+
#elif defined(Q_PROCESSOR_X86)
#ifdef Q_PROCESSOR_X86_32
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index 26e98c45423..7ad2b200076 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -164,6 +164,16 @@
# if !defined(__MIPS_DSPR2__) && defined(__mips_dspr2) && defined(Q_PROCESSOR_MIPS_32)
# define __MIPS_DSPR2__
# endif
+#elif defined(Q_PROCESSOR_LOONGARCH)
+# define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x)
+# if defined(Q_CC_GNU)
+ /* GCC requires attributes for a function */
+# define QT_FUNCTION_TARGET_STRING_lsx "lsx"
+# define QT_FUNCTION_TARGET_STRING_lasx "lasx"
+# define QT_FUNCTION_TARGET(x) __attribute__((__target__(QT_FUNCTION_TARGET_STRING_ ## x)))
+# else
+# define QT_FUNCTION_TARGET(x)
+# endif
#elif defined(Q_PROCESSOR_X86) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)
# define QT_COMPILER_SUPPORTS_HERE(x) ((__ ## x ## __) || QT_COMPILER_SUPPORTS(x))
# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
@@ -177,6 +187,16 @@
# define QT_FUNCTION_TARGET(x)
#endif
+/* -- loongarch64 intrinsic support -- */
+#ifdef __loongarch_asx
+// #include the intrinsics
+# include<lsxintrin.h>
+# include<lasxintrin.h>
+#elif defined __loongarch_sx
+// #include the intrinsics
+# include<lsxintrin.h>
+#endif
+
#ifdef Q_PROCESSOR_X86
/* -- x86 intrinsic support -- */
@@ -317,6 +337,9 @@ enum CPUFeatures {
#elif defined(Q_PROCESSOR_MIPS)
CpuFeatureDSP = 2,
CpuFeatureDSPR2 = 4,
+#elif defined(Q_PROCESSOR_LOONGARCH)
+ CpuFeatureLSX = 2,
+ CpuFeatureLASX = 4,
#endif
// used only to indicate that the CPU detection was initialised
@@ -335,6 +358,12 @@ static const quint64 qCompilerCpuFeatures = 0
#endif
#if defined __mips_dspr2
| CpuFeatureDSPR2
+#endif
+#if defined __loongarch_sx
+ | CpuFeatureLSX
+#endif
+#if defined __loongarch_asx
+ | CpuFeatureLASX
#endif
;
#endif
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index 01e48c17ddd..ed9a1a19c2b 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -92,6 +92,8 @@ qtConfig(png) {
# SIMD
!android {
SSSE3_SOURCES += image/qimage_ssse3.cpp
+ LSX_SOURCES += image/qimage_lsx.cpp
+ LASX_SOURCES += image/qimage_lasx.cpp
NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 9257ab8cfeb..a0ae270cd10 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -162,6 +162,9 @@ extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src
#elif defined(__ARM_NEON__) && (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
extern void QT_FASTCALL storeRGB32FromARGB32PM_neon(uchar *dest, const uint *src, int index, int count,
const QVector<QRgb> *, QDitherInfo *);
+#elif defined QT_COMPILER_SUPPORTS_LSX
+extern void QT_FASTCALL storeRGB32FromARGB32PM_lsx(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
#endif
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
@@ -187,6 +190,11 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
store = storeRGB32FromARGB32PM_sse4;
else
store = storeRGB32FromARGB32PM;
+#elif defined QT_COMPILER_SUPPORTS_LSX
+ if (qCpuHasFeature(LSX))
+ store = storeRGB32FromARGB32PM_lsx;
+ else
+ store = storeRGB32FromARGB32PM;
#elif defined(__ARM_NEON__) && (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
store = storeRGB32FromARGB32PM_neon;
#else
@@ -351,6 +359,11 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
store = storeRGB32FromARGB32PM_sse4;
else
store = storeRGB32FromARGB32PM;
+#elif defined QT_COMPILER_SUPPORTS_LSX
+ if (qCpuHasFeature(LSX))
+ store = storeRGB32FromARGB32PM_lsx;
+ else
+ store = storeRGB32FromARGB32PM;
#elif defined(__ARM_NEON__) && (Q_BYTE_ORDER == Q_LITTLE_ENDIAN)
store = storeRGB32FromARGB32PM_neon;
#else
@@ -2416,6 +2429,28 @@ static void qInitImageConversions()
}
#endif
+#if defined(QT_COMPILER_SUPPORTS_LASX)
+ if (qCpuHasFeature(LASX)) {
+ extern void convert_RGB888_to_RGB32_lasx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_lasx;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_lasx;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_lasx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBX8888] = convert_RGB888_to_RGB32_lasx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888] = convert_RGB888_to_RGB32_lasx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB32_lasx;
+ }
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX)) {
+ extern void convert_RGB888_to_RGB32_lsx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_lsx;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_lsx;
+ qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_lsx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBX8888] = convert_RGB888_to_RGB32_lsx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888] = convert_RGB888_to_RGB32_lsx;
+ qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB32_lsx;
+ }
+#endif
+
#if defined(__ARM_NEON__)
extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon;
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index b272377fb2e..683262cd152 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -365,7 +365,7 @@ inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format)
inline QImage::Format qt_alphaVersionForPainting(QImage::Format format)
{
QImage::Format toFormat = qt_alphaVersion(format);
-#if defined(__ARM_NEON__) || defined(__SSE2__)
+#if defined(__ARM_NEON__) || defined(__SSE2__) || defined(QT_COMPILE_SUPPORTS_LSX)
// If we are switching depth anyway and we have optimized ARGB32PM routines, upgrade to that.
if (qt_depthForFormat(format) != qt_depthForFormat(toFormat) && qt_depthForFormat(toFormat) <= 32)
toFormat = QImage::Format_ARGB32_Premultiplied;
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index bb0fc0ffbae..2be984edb12 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -21,7 +21,9 @@ HEADERS += \
painting/qdatabuffer_p.h \
painting/qdrawhelper_p.h \
painting/qdrawhelper_x86_p.h \
+ painting/qdrawhelper_loongarch64_p.h \
painting/qdrawingprimitive_sse2_p.h \
+ painting/qdrawingprimitive_lsx_p.h \
painting/qemulationpaintengine_p.h \
painting/qfixed_p.h \
painting/qgrayraster_p.h \
@@ -135,6 +137,10 @@ gcc:equals(QT_GCC_MAJOR_VERSION, 5) {
NO_PCH_SOURCES += painting/qdrawhelper.cpp
}
+lsx{
+ QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_LSX
+}
+
!android {
SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
@@ -142,6 +148,10 @@ gcc:equals(QT_GCC_MAJOR_VERSION, 5) {
painting/qimagescale_sse4.cpp
ARCH_HASWELL_SOURCES += painting/qdrawhelper_avx2.cpp
+ LSX_SOURCES += painting/qdrawhelper_lsx.cpp \
+ painting/qimagescale_lsx.cpp
+ LASX_SOURCES += painting/qdrawhelper_lasx.cpp
+
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
}
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index aa3f1489342..a94b5c4c261 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -247,6 +247,73 @@ struct Rgba64OperationsSSE2 : public Rgba64OperationsBase
};
#endif
+#if defined(__loongarch_sx)
+struct Rgba64OperationsLSX : public Rgba64OperationsBase
+{
+ typedef __m128i OptimalType;
+ typedef __m128i OptimalScalar;
+ static OptimalType load(const Type *ptr)
+ {
+ return __lsx_vilvl_d(__lsx_vldi(0), __lsx_vldrepl_d(ptr, 0));
+ }
+ static OptimalType convert(const Type &value)
+ {
+ return __lsx_vinsgr2vr_d(__lsx_vldi(0), value, 0);
+ }
+ static void store(Type *ptr, OptimalType value)
+ {
+ __lsx_vstelm_d(value, ptr, 0, 0);
+ }
+ static OptimalType add(OptimalType a, OptimalType b)
+ {
+ return __lsx_vadd_h(a, b);
+ }
+// same as above:
+// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
+ static OptimalType plus(OptimalType a, OptimalType b)
+ {
+ return __lsx_vsadd_hu(a, b);
+ }
+ static OptimalScalar alpha(OptimalType c)
+ {
+ const __m128i shuffleMask = (__m128i)(v8i16){3, 3, 3, 3, 4, 5, 6, 7};
+ return __lsx_vshuf_h(shuffleMask, __lsx_vldi(0), c);
+ }
+ static OptimalScalar invAlpha(Scalar c)
+ {
+ return scalar(65535 - c);
+ }
+ static OptimalScalar invAlpha(OptimalType c)
+ {
+ return __lsx_vxor_v(__lsx_vreplgr2vr_h(-1), alpha(c));
+ }
+ static OptimalScalar scalar(Scalar n)
+ {
+ const __m128i shuffleMask = (__m128i)(v8i16){0, 0, 0, 0, 4, 5, 6, 7};
+ return __lsx_vshuf_h(shuffleMask, __lsx_vldi(0), __lsx_vinsgr2vr_w(__lsx_vldi(0), n, 0));
+ }
+ static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ {
+ return multiplyAlpha255(val, a);
+ }
+// same as above:
+// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
+ static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ {
+ return interpolate255(x, a1, y, a2);
+ }
+ static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ {
+ return multiplyAlpha65535(val, a);
+ }
+ static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, const OptimalScalar &a2)
+ {
+ return interpolate65535(x, a1, y, a2);
+ }
+};
+#endif
+
+
#if defined(__ARM_NEON__)
struct Rgba64OperationsNEON : public Rgba64OperationsBase
{
@@ -314,6 +381,8 @@ struct Rgba64OperationsNEON : public Rgba64OperationsBase
#if defined(__SSE2__)
typedef Rgba64OperationsSSE2 Rgba64Operations;
+#elif defined(__loongarch_sx)
+typedef Rgba64OperationsLSX Rgba64Operations;
#elif defined(__ARM_NEON__)
typedef Rgba64OperationsNEON Rgba64Operations;
#else
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index a61793508ac..2d993cab1b7 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -37,7 +37,6 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#include <qglobal.h>
#include <qstylehints.h>
@@ -48,6 +47,8 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
#include <private/qdrawhelper_x86_p.h>
+#include <private/qdrawhelper_loongarch64_p.h>
+#include <private/qdrawingprimitive_lsx_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
#include <private/qdrawhelper_neon_p.h>
#if defined(QT_COMPILER_SUPPORTS_MIPS_DSP) || defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
@@ -354,6 +355,8 @@ static void QT_FASTCALL convertToRGB32(uint *buffer, int count, const QVector<QR
#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
extern const uint * QT_FASTCALL fetchPixelsBPP24_ssse3(uint *dest, const uchar*src, int index, int count);
+#elif defined QT_COMPILER_SUPPORTS_LSX
+extern const uint * QT_FASTCALL fetchPixelsBPP24_lsx(uint *dest, const uchar*src, int index, int count);
#endif
template<QImage::Format Format>
@@ -369,6 +372,12 @@ static const uint *QT_FASTCALL fetchRGBToRGB32(uint *buffer, const uchar *src, i
convertToRGB32<Format>(buffer, count, nullptr);
return buffer;
}
+#elif defined QT_COMPILER_SUPPORTS_LSX
+ if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(LSX)) {
+ fetchPixelsBPP24_lsx(buffer, src, index, count);
+ convertToRGB32<Format>(buffer, count, nullptr);
+ return buffer;
+ }
#endif
for (int i = 0; i < count; ++i)
buffer[i] = convertPixelToRGB32<Format>(fetchPixel<BPP>(src, index + i));
@@ -460,6 +469,12 @@ static const uint *QT_FASTCALL fetchARGBPMToARGB32PM(uint *buffer, const uchar *
convertARGBPMToARGB32PM<Format>(buffer, count, nullptr);
return buffer;
}
+#elif defined QT_COMPILER_SUPPORTS_LSX
+ if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(LSX)) {
+ fetchPixelsBPP24_lsx(buffer, src, index, count);
+ convertARGBPMToARGB32PM<Format>(buffer, count, nullptr);
+ return buffer;
+ }
#endif
for (int i = 0; i < count; ++i)
buffer[i] = convertPixelToARGB32PM<Format>(fetchPixel<BPP>(src, index + i));
@@ -1021,6 +1036,110 @@ static inline void qConvertRGBA64PMToA2RGB30PM_sse2(uint *dest, const QRgba64 *b
SIMD_EPILOGUE(i, count, 15)
*dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
}
+
+#elif defined __loongarch_sx
+template<bool RGBA, bool maskAlpha>
+static inline void qConvertARGB32PMToRGBA64PM_lsx(QRgba64 *buffer, const uint *src, int count)
+{
+ if (count <= 0)
+ return;
+
+ const __m128i amask = __lsx_vreplgr2vr_w(0xff000000);
+ const __m128i shuffleMask = (__m128i)(v8i16){2, 1, 0, 3, 6, 5, 4, 7};
+ 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);
+ }
+ for (; i < count-3; i += 4) {
+ __m128i vs = __lsx_vld((const __m128i*)src, 0);
+ if (maskAlpha)
+ vs = __lsx_vor_v(vs, amask);
+ src += 4;
+ __m128i v1 = __lsx_vilvl_b(vs, vs);
+ __m128i v2 = __lsx_vilvh_b(vs, vs);
+ if (!RGBA) {
+ v1 = __lsx_vshuf_h(shuffleMask, v1, v1);
+ v2 = __lsx_vshuf_h(shuffleMask, v2, v2);
+ }
+ __lsx_vst(v1, buffer, 0);
+ buffer += 2;
+ __lsx_vst(v2, buffer, 0);
+ buffer += 2;
+ }
+
+ SIMD_EPILOGUE(i, count, 3) {
+ uint s = *src++;
+ if (maskAlpha)
+ s = s | 0xff000000;
+ if (RGBA)
+ s = RGBA2ARGB(s);
+ *buffer++ = QRgba64::fromArgb32(s);
+ }
+}
+
+template<QtPixelOrder PixelOrder>
+static inline void qConvertRGBA64PMToA2RGB30PM_lsx(uint *dest, const QRgba64 *buffer, int count)
+{
+ const __m128i gmask = __lsx_vreplgr2vr_w(0x000ffc00);
+ const __m128i cmask = __lsx_vreplgr2vr_w(0x000003ff);
+ int i = 0;
+ __m128i vr, vg, vb, va;
+ for (; i < count && uintptr_t(buffer) & 0xF; ++i) {
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+ }
+
+ for (; i < count-15; i += 16) {
+ __m128i vOr = __lsx_vreplgr2vr_w(0);
+ __m128i vAnd = __lsx_vreplgr2vr_w(0xffffffff);
+ for (int j = 0; j < 16; j += 2) {
+ __m128i vs = __lsx_vld((const __m128i*)(buffer + j), 0);
+ vOr = __lsx_vor_v(vOr, vs);
+ vAnd = __lsx_vand_v(vAnd, vs);
+ }
+ const quint16 orAlpha = ((uint)__lsx_vpickve2gr_h(vOr, 3)) | ((uint)__lsx_vpickve2gr_h(vOr, 7));
+ const quint16 andAlpha = ((uint)__lsx_vpickve2gr_h(vAnd, 3)) & ((uint)__lsx_vpickve2gr_h(vAnd, 7));
+
+ if (andAlpha == 0xffff) {
+ for (int j = 0; j < 16; j += 2) {
+ __m128i vs = __lsx_vld((const __m128i*)buffer, 0);
+ buffer += 2;
+ vr = __lsx_vsrli_d(vs, 6);
+ vg = __lsx_vsrli_d(vs, 16 + 6 - 10);
+ vb = __lsx_vsrli_d(vs, 32 + 6);
+ vr = __lsx_vand_v(vr, cmask);
+ vg = __lsx_vand_v(vg, gmask);
+ vb = __lsx_vand_v(vb, cmask);
+ va = __lsx_vsrli_d(vs, 48 + 14);
+ if (PixelOrder == PixelOrderRGB)
+ vr = __lsx_vslli_w(vr, 20);
+ else
+ vb = __lsx_vslli_w(vb, 20);
+ va = __lsx_vslli_w(va, 30);
+ __m128i vd = __lsx_vor_v(__lsx_vor_v(vr, vg), __lsx_vor_v(vb, va));
+ vd = __lsx_vshuf4i_w(vd, 0b11011000);
+ __lsx_vstelm_d(vd, dest, 0, 0);
+ dest += 2;
+ }
+ } else if (orAlpha == 0) {
+ for (int j = 0; j < 16; ++j) {
+ *dest++ = 0;
+ buffer++;
+ }
+ } else {
+ for (int j = 0; j < 16; ++j)
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+ }
+ }
+
+ SIMD_EPILOGUE(i, count, 15)
+ *dest++ = qConvertRgb64ToRgb30<PixelOrder>(*buffer++);
+}
+
#elif defined(__ARM_NEON__)
template<bool RGBA, bool maskAlpha>
static inline void qConvertARGB32PMToRGBA64PM_neon(QRgba64 *buffer, const uint *src, int count)
@@ -1070,11 +1189,72 @@ static inline void qConvertARGB32PMToRGBA64PM_neon(QRgba64 *buffer, const uint *
}
#endif
+#if defined __loongarch_asx
+template<bool RGBA, bool maskAlpha>
+static inline void qConvertARGB32PMToRGBA64PM_lasx(QRgba64 *buffer, const uint *src, int count)
+{
+ if (count <= 0)
+ return;
+ const __m256i amask = __lasx_xvreplgr2vr_w(0xff000000);
+ const __m256i shuffleMask = (__m256i)(v16i16){2, 1, 0, 3, 6, 5, 4, 7, 2, 1, 0, 3, 6, 5, 4, 7};
+ 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);
+ }
+ for (; i < count-7; i += 8) {
+ __m256i vs = __lasx_xvld((const __m256i*)src, 0);
+ if (maskAlpha)
+ vs = __lasx_xvor_v(vs, amask);
+ src += 8;
+ __m256i v1 = __lasx_xvilvl_b(vs, vs);
+ __m256i v2 = __lasx_xvilvh_b(vs, vs);
+ if (!RGBA) {
+ v1 = __lasx_xvshuf_h(shuffleMask, v1, v1);
+ v2 = __lasx_xvshuf_h(shuffleMask, v2, v2);
+ }
+ __lasx_xvstelm_d(v1, buffer, 0, 0);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 1);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 0);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 1);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 2);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 3);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 2);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 3);
+ buffer ++;
+ }
+
+ SIMD_EPILOGUE(i, count, 7) {
+ uint s = *src++;
+ if (maskAlpha)
+ s = s | 0xff000000;
+ if (RGBA)
+ s = RGBA2ARGB(s);
+ *buffer++ = QRgba64::fromArgb32(s);
+ }
+}
+#endif //__loongarch_asx
+
static const QRgba64 *QT_FASTCALL convertRGB32ToRGB64(QRgba64 *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
#ifdef __SSE2__
qConvertARGB32PMToRGBA64PM_sse2<false, true>(buffer, src, count);
+#elif defined(__loongarch_asx)
+ qConvertARGB32PMToRGBA64PM_lasx<false, true>(buffer, src, count);
+#elif defined(__loongarch_sx)
+ qConvertARGB32PMToRGBA64PM_lsx<false, true>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<false, true>(buffer, src, count);
#else
@@ -1109,6 +1289,10 @@ static const QRgba64 *QT_FASTCALL convertARGB32PMToRGBA64PM(QRgba64 *buffer, con
{
#ifdef __SSE2__
qConvertARGB32PMToRGBA64PM_sse2<false, false>(buffer, src, count);
+#elif defined(__loongarch_asx)
+ qConvertARGB32PMToRGBA64PM_lasx<false, false>(buffer, src, count);
+#elif defined(__loongarch_sx)
+ qConvertARGB32PMToRGBA64PM_lsx<false, false>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<false, false>(buffer, src, count);
#else
@@ -1164,6 +1348,10 @@ static const QRgba64 *QT_FASTCALL convertRGBA8888PMToRGBA64PM(QRgba64 *buffer, c
{
#ifdef __SSE2__
qConvertARGB32PMToRGBA64PM_sse2<true, false>(buffer, src, count);
+#elif defined(__loongarch_asx)
+ qConvertARGB32PMToRGBA64PM_lasx<true, false>(buffer, src, count);
+#elif defined(__loongarch_sx)
+ qConvertARGB32PMToRGBA64PM_lsx<true, false>(buffer, src, count);
#elif defined(__ARM_NEON__)
qConvertARGB32PMToRGBA64PM_neon<true, false>(buffer, src, count);
#else
@@ -1276,6 +1464,104 @@ static inline void qConvertA2RGB30PMToRGBA64PM_sse2(QRgba64 *buffer, const uint
SIMD_EPILOGUE(i, count, 3)
*buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
}
+#elif defined(__loongarch_asx)
+template<QtPixelOrder PixelOrder>
+static inline void qConvertA2RGB30PMToRGBA64PM_lasx(QRgba64 *buffer, const uint *src, int count)
+{
+ if (count <= 0)
+ return;
+
+ const __m256i rmask = __lasx_xvreplgr2vr_w(0x3ff00000);
+ const __m256i gmask = __lasx_xvreplgr2vr_w(0x000ffc00);
+ const __m256i bmask = __lasx_xvreplgr2vr_w(0x000003ff);
+ const __m256i afactor = __lasx_xvreplgr2vr_h(0x5555);
+ int i = 0;
+
+ for (; ((uintptr_t)buffer & 0xf) && i < count; ++i)
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+
+ for (; i < count-7; i += 8) {
+ __m256i vs = __lasx_xvld((const __m256i*)src, 0);
+ src += 8;
+ __m256i va = __lasx_xvsrli_w(vs, 30);
+ __m256i vr = __lasx_xvand_v(vs, rmask);
+ __m256i vb = __lasx_xvand_v(vs, bmask);
+ __m256i vg = __lasx_xvand_v(vs, gmask);
+ va = __lasx_xvmul_h(va, afactor);
+ vr = __lasx_xvor_v(__lasx_xvsrli_w(vr, 14), __lasx_xvsrli_w(vr, 24));
+ vg = __lasx_xvor_v(__lasx_xvsrli_w(vg, 4), __lasx_xvsrli_w(vg, 14));
+ vb = __lasx_xvor_v(__lasx_xvslli_w(vb, 6), __lasx_xvsrli_w(vb, 4));
+ __m256i vrb;
+ if (PixelOrder == PixelOrderRGB)
+ vrb = __lasx_xvor_v(vr, __lasx_xvbsll_v(vb, 2));
+ else
+ vrb = __lasx_xvor_v(vb, __lasx_xvbsll_v(vr, 2));
+ __m256i vga = __lasx_xvor_v(vg, __lasx_xvbsll_v(va, 2));
+ __m256i v1 = __lasx_xvilvl_h(vga, vrb);
+ __m256i v2 = __lasx_xvilvh_h(vga, vrb);
+ __lasx_xvstelm_d(v1, buffer, 0, 0);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 1);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 0);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 1);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 2);
+ buffer ++;
+ __lasx_xvstelm_d(v1, buffer, 0, 3);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 2);
+ buffer ++;
+ __lasx_xvstelm_d(v2, buffer, 0, 3);
+ buffer ++;
+ }
+
+ SIMD_EPILOGUE(i, count, 7)
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+}
+#elif defined(__loongarch_sx)
+template<QtPixelOrder PixelOrder>
+static inline void qConvertA2RGB30PMToRGBA64PM_lsx(QRgba64 *buffer, const uint *src, int count)
+{
+ if (count <= 0)
+ return;
+
+ const __m128i rmask = __lsx_vreplgr2vr_w(0x3ff00000);
+ const __m128i gmask = __lsx_vreplgr2vr_w(0x000ffc00);
+ const __m128i bmask = __lsx_vreplgr2vr_w(0x000003ff);
+ const __m128i afactor = __lsx_vreplgr2vr_h(0x5555);
+ int i = 0;
+
+ for (; ((uintptr_t)buffer & 0xf) && i < count; ++i)
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+
+ for (; i < count-3; i += 4) {
+ __m128i vs = __lsx_vld((const __m128i*)src, 0);
+ src += 4;
+ __m128i va = __lsx_vsrli_w(vs, 30);
+ __m128i vr = __lsx_vand_v(vs, rmask);
+ __m128i vb = __lsx_vand_v(vs, bmask);
+ __m128i vg = __lsx_vand_v(vs, gmask);
+ va = __lsx_vmul_h(va, afactor);
+ vr = __lsx_vor_v(__lsx_vsrli_w(vr, 14), __lsx_vsrli_w(vr, 24));
+ vg = __lsx_vor_v(__lsx_vsrli_w(vg, 4), __lsx_vsrli_w(vg, 14));
+ vb = __lsx_vor_v(__lsx_vslli_w(vb, 6), __lsx_vsrli_w(vb, 4));
+ __m128i vrb;
+ if (PixelOrder == PixelOrderRGB)
+ vrb = __lsx_vor_v(vr, __lsx_vbsll_v(vb, 2));
+ else
+ vrb = __lsx_vor_v(vb, __lsx_vbsll_v(vr, 2));
+ __m128i vga = __lsx_vor_v(vg, __lsx_vbsll_v(va, 2));
+ __lsx_vst(__lsx_vilvl_h(vga, vrb), buffer, 0);
+ buffer += 2;
+ __lsx_vst(__lsx_vilvh_h(vga, vrb), buffer, 0);
+ buffer += 2;
+ }
+
+ SIMD_EPILOGUE(i, count, 3)
+ *buffer++ = qConvertA2rgb30ToRgb64<PixelOrder>(*src++);
+}
#endif
template<QtPixelOrder PixelOrder>
@@ -1284,6 +1570,10 @@ static const QRgba64 *QT_FASTCALL convertA2RGB30PMToRGBA64PM(QRgba64 *buffer, co
{
#ifdef __SSE2__
qConvertA2RGB30PMToRGBA64PM_sse2<PixelOrder>(buffer, src, count);
+#elif defined (__loongarch_asx)
+ qConvertA2RGB30PMToRGBA64PM_lasx<PixelOrder>(buffer, src, count);
+#elif defined (__loongarch_sx)
+ qConvertA2RGB30PMToRGBA64PM_lsx<PixelOrder>(buffer, src, count);
#else
for (int i = 0; i < count; ++i)
buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]);
@@ -1356,6 +1646,37 @@ void qt_convertRGBA64ToARGB32(uint *dst, const QRgba64 *src, int count)
_mm_storel_epi64((__m128i*)(dst), v1);
dst += 2;
}
+#elif defined(__loongarch_sx)
+ if (((uintptr_t)dst & 0x7) && count > 0) {
+ uint s = (*src++).toArgb32();
+ if (RGBA)
+ s = ARGB2RGBA(s);
+ *dst++ = s;
+ i++;
+ }
+ const __m128i vhalf = __lsx_vreplgr2vr_w(0x80);
+ const __m128i vzero = {0, 0};
+ const __m128i shuffleMask = (__m128i)(v8i16){2,1,0,3,6,5,4,7};
+ for (; i < count-1; i += 2) {
+ __m128i vs = __lsx_vld((const __m128i*)src, 0);
+ src += 2;
+ if (!RGBA) {
+ vs = __lsx_vshuf_h(shuffleMask, vzero, vs);
+ }
+ __m128i v1 = __lsx_vilvl_h(vzero, vs);
+ __m128i v2 = __lsx_vilvh_h(vzero, vs);
+ v1 = __lsx_vadd_w(v1, vhalf);
+ v2 = __lsx_vadd_w(v2, vhalf);
+ v1 = __lsx_vsub_w(v1, __lsx_vsrli_w(v1, 8));
+ v2 = __lsx_vsub_w(v2, __lsx_vsrli_w(v2, 8));
+ v1 = __lsx_vsrli_w(v1, 8);
+ v2 = __lsx_vsrli_w(v2, 8);
+ v1 = __lsx_vpickev_h(__lsx_vsat_w(v2, 15), __lsx_vsat_w(v1, 15));
+ v1 = __lsx_vmaxi_h(v1, 0);
+ v1 = __lsx_vpickev_b(vzero, __lsx_vsat_hu(v1, 7));
+ __lsx_vstelm_d(v1, dst, 0, 0);
+ dst += 2;
+ }
#endif
for (; i < count; i++) {
uint s = (*src++).toArgb32();
@@ -1592,6 +1913,8 @@ static void QT_FASTCALL storeRGB30FromRGBA64PM(uchar *dest, const QRgba64 *src,
uint *d = (uint*)dest + index;
#ifdef __SSE2__
qConvertRGBA64PMToA2RGB30PM_sse2<PixelOrder>(d, src, count);
+#elif defined (__loongarch_sx)
+ qConvertRGBA64PMToA2RGB30PM_lsx<PixelOrder>(d, src, count);
#else
for (int i = 0; i < count; ++i)
d[i] = qConvertRgb64ToRgb30<PixelOrder>(src[i]);
@@ -2350,6 +2673,43 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, u
}
#endif
+#if defined(__loongarch_sx)
+#define interpolate_4_pixels_16_lsx(tl, tr, bl, br, distx, disty, colorMask, v_256, b) \
+{ \
+ const __m128i dxdy = __lsx_vmul_h(distx, disty); \
+ const __m128i distx_ = __lsx_vslli_h(distx, 4); \
+ const __m128i disty_ = __lsx_vslli_h(disty, 4); \
+ const __m128i idxidy = __lsx_vadd_h(dxdy, __lsx_vsub_h(v_256, __lsx_vadd_h(distx_, disty_)));\
+ const __m128i dxidy = __lsx_vsub_h(distx_, dxdy);\
+ const __m128i idxdy = __lsx_vsub_h(disty_,dxdy);\
+ \
+ __m128i tlAG = __lsx_vsrli_h(tl, 8); \
+ __m128i tlRB = __lsx_vand_v(tl, colorMask); \
+ __m128i trAG = __lsx_vsrli_h(tr, 8); \
+ __m128i trRB = __lsx_vand_v(tr, colorMask); \
+ __m128i blAG = __lsx_vsrli_h(bl, 8); \
+ __m128i blRB = __lsx_vand_v(bl, colorMask); \
+ __m128i brAG = __lsx_vsrli_h(br, 8); \
+ __m128i brRB = __lsx_vand_v(br, colorMask); \
+ \
+ tlAG = __lsx_vmul_h(tlAG, idxidy); \
+ tlRB = __lsx_vmul_h(tlRB, idxidy); \
+ trAG = __lsx_vmul_h(trAG, dxidy); \
+ trRB = __lsx_vmul_h(trRB, dxidy); \
+ blAG = __lsx_vmul_h(blAG, idxdy); \
+ blRB = __lsx_vmul_h(blRB, idxdy); \
+ brAG = __lsx_vmul_h(brAG, dxdy); \
+ brRB = __lsx_vmul_h(brRB, dxdy); \
+ \
+ /* Add the values, and shift to only keep 8 significant bits per colors */ \
+ __m128i rAG =__lsx_vadd_h(__lsx_vadd_h(tlAG, trAG), __lsx_vadd_h(blAG, brAG)); \
+ __m128i rRB =__lsx_vadd_h(__lsx_vadd_h(tlRB, trRB), __lsx_vadd_h(blRB, brRB)); \
+ rAG = __lsx_vandn_v(colorMask, rAG); \
+ rRB = __lsx_vsrli_h(rRB, 8); \
+ __lsx_vst(__lsx_vor_v(rAG, rRB), b, 0); \
+}
+#endif
+
#if defined(__ARM_NEON__)
#define interpolate_4_pixels_16_neon(tl, tr, bl, br, distx, disty, disty_, colorMask, invColorMask, v_256, b) \
{ \
@@ -2699,6 +3059,35 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper(uint *
v_fx = _mm_add_epi32(v_fx, v_fdx);
}
fx = _mm_cvtsi128_si32(v_fx);
+#elif defined (__loongarch_sx)
+ const __m128i shuffleMask = (__m128i)(v8i16){0,0,2,2,4,4,6,6};
+ const __m128i colorMask = __lsx_vreplgr2vr_w(0x00ff00ff);
+ const __m128i v_256 = __lsx_vreplgr2vr_h(256);
+ const __m128i v_disty = __lsx_vreplgr2vr_h(disty4);
+ const __m128i v_fdx = __lsx_vreplgr2vr_w(fdx*4);
+ const __m128i v_fx_r = __lsx_vreplgr2vr_w(0x8);
+ __m128i v_fx = (__m128i)(v4i32){fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx};
+
+ while (b < boundedEnd - 3) {
+ __m128i offset = __lsx_vsrli_w(v_fx, 16);
+ const int offset0 = __lsx_vpickve2gr_w(offset, 0);
+ const int offset1 = __lsx_vpickve2gr_w(offset, 1);
+ const int offset2 = __lsx_vpickve2gr_w(offset, 2);
+ const int offset3 = __lsx_vpickve2gr_w(offset, 3);
+ const __m128i tl = (__m128i)(v4u32){s1[offset0], s1[offset1], s1[offset2], s1[offset3]};
+ const __m128i tr = (__m128i)(v4u32){s1[offset0 + 1], s1[offset1 + 1], s1[offset2 + 1], s1[offset3 + 1]};
+ const __m128i bl = (__m128i)(v4u32){s2[offset0], s2[offset1], s2[offset2], s2[offset3]};
+ const __m128i br = (__m128i)(v4u32){s2[offset0 + 1], s2[offset1 + 1], s2[offset2 + 1], s2[offset3 + 1]};
+
+ __m128i v_distx = __lsx_vsrli_h(v_fx, 8);
+ v_distx = __lsx_vsrli_h(__lsx_vadd_w(v_distx, v_fx_r), 4);
+ v_distx = __lsx_vshuf_h(shuffleMask, v_distx, v_distx);
+
+ interpolate_4_pixels_16_lsx(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b);
+ b += 4;
+ v_fx = __lsx_vadd_w(v_fx, v_fdx);
+ }
+ fx = __lsx_vpickve2gr_w(v_fx, 0);
#elif defined(__ARM_NEON__)
const int16x8_t colorMask = vdupq_n_s16(0x00ff);
const int16x8_t invColorMask = vmvnq_s16(colorMask);
@@ -2909,6 +3298,53 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
}
fx = _mm_cvtsi128_si32(v_fx);
fy = _mm_cvtsi128_si32(v_fy);
+#elif defined(__loongarch_sx)
+ const __m128i colorMask = __lsx_vreplgr2vr_w(0x00ff00ff);
+ const __m128i v_256 = __lsx_vreplgr2vr_h(256);
+ const __m128i v_fdx = __lsx_vreplgr2vr_w(fdx*4);
+ const __m128i v_fdy = __lsx_vreplgr2vr_w(fdy*4);
+ const __m128i v_fxy_r = __lsx_vreplgr2vr_w(0x8);
+ __m128i v_fx = (__m128i)(v4i32){fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx};
+ __m128i v_fy = (__m128i)(v4i32){fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy};
+
+ const uchar *textureData = image.imageData;
+ const qsizetype bytesPerLine = image.bytesPerLine;
+ const __m128i zero = {0,0};
+ const __m128i shuffleMask = (__m128i)(v8i16){0,0,0,0,4,5,6,7};
+ const __m128i shuffleMask1 = (__m128i)(v8i16){0,0,2,2,4,4,6,6};
+ const __m128i vbpl = __lsx_vshuf_h(shuffleMask, zero, __lsx_vinsgr2vr_w(zero, bytesPerLine/4, 0));
+
+ while (b < boundedEnd - 3) {
+ const __m128i vy = __lsx_vpickev_h(zero, __lsx_vsat_w(__lsx_vsrli_w(v_fy, 16), 15));
+ // 4x16bit * 4x16bit -> 4x32bit
+ __m128i offset = __lsx_vilvl_h(__lsx_vmuh_h(vy, vbpl), __lsx_vmul_h(vy, vbpl));
+ offset = __lsx_vadd_w(offset, __lsx_vsrli_w(v_fx, 16));
+ const int offset0 = __lsx_vpickve2gr_w(offset, 0);
+ const int offset1 = __lsx_vpickve2gr_w(offset, 1);
+ const int offset2 = __lsx_vpickve2gr_w(offset, 2);
+ const int offset3 = __lsx_vpickve2gr_w(offset, 3);
+ const uint *topData = (const uint *)(textureData);
+ const __m128i tl = (__m128i)(v4u32){topData[offset0], topData[offset1], topData[offset2], topData[offset3]};
+ const __m128i tr = (__m128i)(v4u32){topData[offset0 + 1], topData[offset1 + 1], topData[offset2 + 1], topData[offset3 + 1]};
+ const uint *bottomData = (const uint *)(textureData + bytesPerLine);
+ const __m128i bl = (__m128i)(v4u32){bottomData[offset0], bottomData[offset1], bottomData[offset2], bottomData[offset3]};
+ const __m128i br = (__m128i)(v4u32){bottomData[offset0 + 1], bottomData[offset1 + 1], bottomData[offset2 + 1], bottomData[offset3 + 1]};
+
+ __m128i v_distx = __lsx_vsrli_h(v_fx, 8);
+ __m128i v_disty = __lsx_vsrli_h(v_fy, 8);
+ v_distx = __lsx_vsrli_h(__lsx_vadd_w(v_distx, v_fxy_r), 4);
+ v_disty = __lsx_vsrli_h(__lsx_vadd_w(v_disty, v_fxy_r), 4);
+ v_distx = __lsx_vshuf_h(shuffleMask1, zero, v_distx);
+ v_disty = __lsx_vshuf_h(shuffleMask1, zero, v_disty);
+
+ interpolate_4_pixels_16_lsx(tl, tr, bl, br, v_distx, v_disty, colorMask, v_256, b);
+ b += 4;
+ v_fx = __lsx_vadd_w(v_fx, v_fdx);
+ v_fy = __lsx_vadd_w(v_fy, v_fdy);
+ }
+ fx = __lsx_vpickve2gr_w(v_fx, 0);
+ fy = __lsx_vpickve2gr_w(v_fy, 0);
+
#elif defined(__ARM_NEON__)
const int16x8_t colorMask = vdupq_n_s16(0x00ff);
const int16x8_t invColorMask = vmvnq_s16(colorMask);
@@ -4538,6 +4974,9 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
#ifdef __SSE2__
} else if (spans->len > 16) {
op.funcSolid(target, spans->len, color, spans->coverage);
+#elif defined(__loongarch_sx)
+ } else if (spans->len > 16) {
+ op.funcSolid(target, spans->len, color, spans->coverage);
#endif
} else {
uint c = BYTE_MUL(color, spans->coverage);
@@ -5432,7 +5871,7 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
proc = processTextureSpansRGB16[blendType];
break;
#if QT_CONFIG(raster_64bit)
-#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
+#if defined(__SSE2__) || defined(__ARM_NEON__) || defined(QT_COMPILER_SUPPORTS_LSX) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
#endif
@@ -5542,7 +5981,7 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
return blend_vertical_gradient_argb(count, spans, userData);
return blend_src_generic(count, spans, userData);
#if QT_CONFIG(raster_64bit)
-#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
+#if defined(__SSE2__) || defined(__ARM_NEON__) || defined(QT_COMPILER_SUPPORTS_LSX) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
case QImage::Format_RGBA8888:
#endif
@@ -6649,7 +7088,7 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
},
};
-#if !defined(__SSE2__)
+#if !defined(__SSE2__) && !defined(QT_COMPILER_SUPPORTS_LSX)
void qt_memfill64(quint64 *dest, quint64 color, qsizetype count)
{
qt_memfill_template<quint64>(dest, color, count);
@@ -6665,6 +7104,10 @@ void qt_memfill24(quint24 *dest, quint24 color, qsizetype count)
extern void qt_memfill24_ssse3(quint24 *, quint24, qsizetype);
if (qCpuHasFeature(SSSE3))
return qt_memfill24_ssse3(dest, color, count);
+# elif defined QT_COMPILER_SUPPORTS_LSX
+ extern void qt_memfill24_lsx(quint24 *, quint24, qsizetype);
+ if (qCpuHasFeature(LSX))
+ return qt_memfill24_lsx(dest, color, count);
# endif
const quint32 v = color;
@@ -6716,7 +7159,7 @@ void qt_memfill16(quint16 *dest, quint16 value, qsizetype count)
qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
}
-#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
+#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__) && !defined(QT_COMPILER_SUPPORTS_LSX)
void qt_memfill32(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill_template<quint32>(dest, color, count);
@@ -6727,10 +7170,19 @@ decltype(qt_memfill32_sse2) *qt_memfill32 = nullptr;
decltype(qt_memfill64_sse2) *qt_memfill64 = nullptr;
#endif
+#ifdef QT_COMPILER_SUPPORTS_LSX
+decltype(qt_memfill32_lsx) *qt_memfill32 = nullptr;
+decltype(qt_memfill64_lsx) *qt_memfill64 = nullptr;
+#endif
+
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *);
#endif
+#if defined QT_COMPILER_SUPPORTS_LSX
+template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_lsx(uchar *dest, const uint *src, int index, int count, const QVector<QRgb> *, QDitherInfo *);
+#endif
+
extern void qInitBlendFunctions();
static void qInitDrawhelperFunctions()
@@ -6941,6 +7393,195 @@ static void qInitDrawhelperFunctions()
#endif // SSE2
+#if defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX)) {
+ qt_memfill32 = qt_memfill32_lsx;
+ qt_memfill64 = qt_memfill64_lsx;
+
+ qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_lsx;
+ qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_lsx;
+ qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_lsx;
+ qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_lsx;
+ qDrawHelper[QImage::Format_RGBX8888].bitmapBlit = qt_bitmapblit8888_lsx;
+ qDrawHelper[QImage::Format_RGBA8888].bitmapBlit = qt_bitmapblit8888_lsx;
+ qDrawHelper[QImage::Format_RGBA8888_Premultiplied].bitmapBlit = qt_bitmapblit8888_lsx;
+
+ extern void qt_scale_image_argb32_on_argb32_lsx(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl, int srch,
+ 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_lsx;
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32_lsx;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_lsx;
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32_lsx;
+
+ extern void qt_blend_rgb32_on_rgb32_lsx(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+ extern void qt_blend_argb32_on_argb32_lsx(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_lsx;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_lsx;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_lsx;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_lsx;
+
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_lsx;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_lsx;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_lsx;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_lsx;
+
+ extern const uint * QT_FASTCALL qt_fetch_radial_gradient_lsx(uint *buffer, const Operator *op, const QSpanData *data,
+ int y, int x, int length);
+
+ qt_fetch_radial_gradient = qt_fetch_radial_gradient_lsx;
+
+ extern void QT_FASTCALL comp_func_SourceOver_lsx(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_lsx(uint *destPixels, int length, uint color, uint const_alpha);
+ extern void QT_FASTCALL comp_func_Source_lsx(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_Source_lsx(uint *destPixels, int length, uint color, uint const_alpha);
+ extern void QT_FASTCALL comp_func_Plus_lsx(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_lsx;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_lsx;
+ qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_lsx;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_Source] = comp_func_solid_Source_lsx;
+ qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_lsx;
+
+ extern const uint * QT_FASTCALL qt_fetchUntransformed_888_lsx(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length);
+ sourceFetchUntransformed[QImage::Format_RGB888] = qt_fetchUntransformed_888_lsx;
+ extern void QT_FASTCALL rbSwap_888_lsx(uchar *dst, const uchar *src, int count);
+ qPixelLayouts[QImage::Format_RGB888].rbSwap = rbSwap_888_lsx;
+ qPixelLayouts[QImage::Format_BGR888].rbSwap = rbSwap_888_lsx;
+
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_lsx(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_lsx(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_lsx(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_lsx(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_lsx(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_lsx(QRgba64 *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_lsx(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_lsx(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeARGB32FromARGB32PM_lsx(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA8888FromARGB32PM_lsx(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBXFromARGB32PM_lsx(uchar *dest, const uint *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeARGB32FromRGBA64PM_lsx(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL storeRGBA8888FromRGBA64PM_lsx(uchar *dest, const QRgba64 *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern void QT_FASTCALL destStore64ARGB32_lsx(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+ extern void QT_FASTCALL destStore64RGBA8888_lsx(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_lsx;
+ qPixelLayouts[QImage::Format_ARGB32].storeFromARGB32PM = storeARGB32FromARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_RGBA8888].storeFromARGB32PM = storeRGBA8888FromARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_RGBX8888].storeFromARGB32PM = storeRGBXFromARGB32PM_lsx;
+ qPixelLayouts[QImage::Format_A2BGR30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_lsx<PixelOrderBGR>;
+ qPixelLayouts[QImage::Format_A2RGB30_Premultiplied].storeFromARGB32PM = storeA2RGB30PMFromARGB32PM_lsx<PixelOrderRGB>;
+ qStoreFromRGBA64PM[QImage::Format_ARGB32] = storeARGB32FromRGBA64PM_lsx;
+ qStoreFromRGBA64PM[QImage::Format_RGBA8888] = storeRGBA8888FromRGBA64PM_lsx;
+#if QT_CONFIG(raster_64bit)
+ destStoreProc64[QImage::Format_ARGB32] = destStore64ARGB32_lsx;
+ destStoreProc64[QImage::Format_RGBA8888] = destStore64RGBA8888_lsx;
+#endif
+ }
+
+#if defined(QT_COMPILER_SUPPORTS_LASX)
+ if (qCpuHasFeature(LASX)) {
+ qt_memfill32 = qt_memfill32_lasx;
+ qt_memfill64 = qt_memfill64_lasx;
+
+ extern void qt_blend_rgb32_on_rgb32_lasx(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h, int const_alpha);
+ extern void qt_blend_argb32_on_argb32_lasx(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_lasx;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_lasx;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_lasx;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_lasx;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_lasx;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32_lasx;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_lasx;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_lasx;
+
+ extern void QT_FASTCALL comp_func_Source_lasx(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_SourceOver_lasx(uint *destPixels, const uint *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_lasx(uint *destPixels, int length, uint color, uint const_alpha);
+ qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_lasx;
+ qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_lasx;
+ qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_lasx;
+#if QT_CONFIG(raster_64bit)
+ extern void QT_FASTCALL comp_func_Source_rgb64_lasx(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_SourceOver_rgb64_lasx(QRgba64 *destPixels, const QRgba64 *srcPixels, int length, uint const_alpha);
+ extern void QT_FASTCALL comp_func_solid_SourceOver_rgb64_lasx(QRgba64 *destPixels, int length, QRgba64 color, uint const_alpha);
+ qt_functionForMode64_C[QPainter::CompositionMode_Source] = comp_func_Source_rgb64_lasx;
+ qt_functionForMode64_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_rgb64_lasx;
+ qt_functionForModeSolid64_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_rgb64_lasx;
+#endif
+
+ extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_simple_scale_helper_lasx(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/);
+ extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper_lasx(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/);
+ extern void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_lasx(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int fdy);
+
+ bilinearFastTransformHelperARGB32PM[0][SimpleScaleTransform] = fetchTransformedBilinearARGB32PM_simple_scale_helper_lasx;
+ bilinearFastTransformHelperARGB32PM[0][DownscaleTransform] = fetchTransformedBilinearARGB32PM_downscale_helper_lasx;
+ bilinearFastTransformHelperARGB32PM[0][FastRotateTransform] = fetchTransformedBilinearARGB32PM_fast_rotate_helper_lasx;
+
+ extern void QT_FASTCALL convertARGB32ToARGB32PM_lasx(uint *buffer, int count, const QVector<QRgb> *);
+ extern void QT_FASTCALL convertRGBA8888ToARGB32PM_lasx(uint *buffer, int count, const QVector<QRgb> *);
+ extern const uint *QT_FASTCALL fetchARGB32ToARGB32PM_lasx(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ extern const uint *QT_FASTCALL fetchRGBA8888ToARGB32PM_lasx(uint *buffer, const uchar *src, int index, int count,
+ const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_lasx;
+ qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_lasx;
+ qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_lasx;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_lasx;
+
+#if QT_CONFIG(raster_64bit)
+ extern const QRgba64 * QT_FASTCALL convertARGB32ToRGBA64PM_lasx(QRgba64 *, const uint *, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 * QT_FASTCALL convertRGBA8888ToRGBA64PM_lasx(QRgba64 *, const uint *, int count, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchARGB32ToRGBA64PM_lasx(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ extern const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_lasx(QRgba64 *, const uchar *, int, int, const QVector<QRgb> *, QDitherInfo *);
+ qPixelLayouts[QImage::Format_ARGB32].convertToRGBA64PM = convertARGB32ToRGBA64PM_lasx;
+ qPixelLayouts[QImage::Format_RGBX8888].convertToRGBA64PM = convertRGBA8888ToRGBA64PM_lasx;
+ qPixelLayouts[QImage::Format_ARGB32].fetchToRGBA64PM = fetchARGB32ToRGBA64PM_lasx;
+ qPixelLayouts[QImage::Format_RGBX8888].fetchToRGBA64PM = fetchRGBA8888ToRGBA64PM_lasx;
+#endif
+ }
+#endif //QT_COMPILER_SUPPORTS_LASX
+
+#endif //QT_COMPILER_SUPPORTS_LSX
+
#if defined(__ARM_NEON__)
qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index b90d0b32027..c5dbf71cd56 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -186,6 +186,9 @@ void qBlendTexture(int count, const QSpan *spans, void *userData);
#ifdef __SSE2__
extern void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count);
extern void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count);
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+extern void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count);
+extern void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count);
#else
extern void qt_memfill64(quint64 *dest, quint64 value, qsizetype count);
extern void qt_memfill32(quint32 *dest, quint32 value, qsizetype count);
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 86057cdd335..f06967d3a51 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -289,6 +289,18 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow);
#endif
+#if defined(QT_COMPILER_SUPPORTS_LSX)
+template<bool RGB>
+void qt_qimageScaleAARGBA_up_x_down_y_lsx(QImageScaleInfo *isi, unsigned int *dest,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_x_up_y_lsx(QImageScaleInfo *isi, unsigned int *dest,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_xy_lsx(QImageScaleInfo *isi, unsigned int *dest,
+ int dw, int dh, int dow, int sow);
+#endif
+
#if defined(__ARM_NEON__)
template<bool RGB>
void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi, unsigned int *dest,
@@ -381,6 +393,10 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dw, dh, dow, sow);
else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_up_x_down_y_lsx<false>(isi, dest, dw, dh, dow, sow);
+ else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
qt_qimageScaleAARGBA_up_x_down_y_neon<false>(isi, dest, dw, dh, dow, sow);
@@ -394,6 +410,10 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dw, dh, dow, sow);
else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_down_x_up_y_lsx<false>(isi, dest, dw, dh, dow, sow);
+ else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
qt_qimageScaleAARGBA_down_x_up_y_neon<false>(isi, dest, dw, dh, dow, sow);
@@ -405,7 +425,11 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
else {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
- qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dw, dh, dow, sow);
+ qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dw, dh, dow, sow);
+ else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_down_xy_lsx<false>(isi, dest, dw, dh, dow, sow);
else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
@@ -810,6 +834,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dw, dh, dow, sow);
else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_up_x_down_y_lsx<true>(isi, dest, dw, dh, dow, sow);
+ else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
qt_qimageScaleAARGBA_up_x_down_y_neon<true>(isi, dest, dw, dh, dow, sow);
@@ -823,6 +851,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dw, dh, dow, sow);
else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_down_x_up_y_lsx<true>(isi, dest, dw, dh, dow, sow);
+ else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
qt_qimageScaleAARGBA_down_x_up_y_neon<true>(isi, dest, dw, dh, dow, sow);
@@ -836,6 +868,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
if (qCpuHasFeature(SSE4_1))
qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dw, dh, dow, sow);
else
+#elif defined(QT_COMPILER_SUPPORTS_LSX)
+ if (qCpuHasFeature(LSX))
+ qt_qimageScaleAARGBA_down_xy_lsx<true>(isi, dest, dw, dh, dow, sow);
+ else
#elif defined(__ARM_NEON__)
if (qCpuHasFeature(NEON))
qt_qimageScaleAARGBA_down_xy_neon<true>(isi, dest, dw, dh, dow, sow);
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index 0a19604c5d3..46220fade9e 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -90,6 +90,26 @@ Q_ALWAYS_INLINE __m128i multiplyAlpha65535(__m128i rgba64, uint alpha65535)
}
#endif
+#if defined(__loongarch_sx)
+Q_ALWAYS_INLINE __m128i multiplyAlpha65535(__m128i rgba64, __m128i va)
+{
+ __m128i vs = rgba64;
+ vs = __lsx_vilvl_h(__lsx_vmuh_hu(vs, va), __lsx_vmul_h(vs, va));
+ vs = __lsx_vadd_w(vs, __lsx_vsrli_w(vs, 16));
+ vs = __lsx_vadd_w(vs, __lsx_vreplgr2vr_w(0x8000));
+ vs = __lsx_vsrai_w(vs, 16);
+ vs = __lsx_vpickev_h(__lsx_vldi(0), __lsx_vsat_w(vs, 15));
+ return vs;
+}
+Q_ALWAYS_INLINE __m128i multiplyAlpha65535(__m128i rgba64, uint alpha65535)
+{
+ const __m128i shuffleMask = (__m128i)(v8i16){0, 0, 0, 0, 4, 5, 6, 7};
+ const __m128i va = __lsx_vshuf_h(shuffleMask, __lsx_vldi(0),
+ __lsx_vinsgr2vr_w(__lsx_vldi(0), alpha65535, 0));
+ return multiplyAlpha65535(rgba64, va);
+}
+#endif
+
#if defined(__ARM_NEON__)
Q_ALWAYS_INLINE uint16x4_t multiplyAlpha65535(uint16x4_t rgba64, uint16x4_t alpha65535)
{
@@ -108,7 +128,7 @@ Q_ALWAYS_INLINE uint16x4_t multiplyAlpha65535(uint16x4_t rgba64, uint alpha65535
template<typename T>
inline T multiplyAlpha255(T rgba64, uint alpha255)
{
-#if defined(__SSE2__) || defined(__ARM_NEON__)
+#if defined(__SSE2__) || defined(__ARM_NEON__) || defined(__loongarch_sx)
return multiplyAlpha65535(rgba64, alpha255 * 257);
#else
return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255),
@@ -130,6 +150,13 @@ Q_ALWAYS_INLINE __m128i interpolate255(__m128i x, uint alpha1, __m128i y, uint a
}
#endif
+#if defined __loongarch_sx
+Q_ALWAYS_INLINE __m128i interpolate255(__m128i x, uint alpha1, __m128i y, uint alpha2)
+{
+ return __lsx_vadd_w(multiplyAlpha255(x, alpha1), multiplyAlpha255(y, alpha2));
+}
+#endif
+
#if defined __ARM_NEON__
Q_ALWAYS_INLINE uint16x4_t interpolate255(uint16x4_t x, uint alpha1, uint16x4_t y, uint alpha2)
{
@@ -154,6 +181,17 @@ Q_ALWAYS_INLINE __m128i interpolate65535(__m128i x, __m128i alpha1, __m128i y, c
}
#endif
+#if defined __loongarch_sx
+Q_ALWAYS_INLINE __m128i interpolate65535(__m128i x, uint alpha1, __m128i y, uint alpha2)
+{
+ return __lsx_vadd_w(multiplyAlpha65535(x, alpha1), multiplyAlpha65535(y, alpha2));
+}
+Q_ALWAYS_INLINE __m128i interpolate65535(__m128i x, __m128i alpha1, __m128i y, const __m128i &alpha2)
+{
+ return __lsx_vadd_w(multiplyAlpha65535(x, alpha1), multiplyAlpha65535(y, alpha2));
+}
+#endif
+
#if defined __ARM_NEON__
Q_ALWAYS_INLINE uint16x4_t interpolate65535(uint16x4_t x, uint alpha1, uint16x4_t y, uint alpha2)
{
@@ -185,6 +223,18 @@ Q_ALWAYS_INLINE uint toArgb32(__m128i v)
v = _mm_packus_epi16(v, v);
return _mm_cvtsi128_si32(v);
}
+#elif defined __loongarch_sx
+Q_ALWAYS_INLINE uint toArgb32(__m128i v)
+{
+ v = __lsx_vilvl_h(__lsx_vldi(0), v);
+ v = __lsx_vadd_w(v, __lsx_vreplgr2vr_w(128));
+ v = __lsx_vsub_w(v, __lsx_vsrli_w(v, 8));
+ v = __lsx_vsrli_w(v, 8);
+ v = __lsx_vpickev_h(__lsx_vsat_w(v, 15), __lsx_vsat_w(v, 15));
+ __m128i tmp = __lsx_vmaxi_h(v, 0);
+ v = __lsx_vpickev_b(__lsx_vsat_hu(tmp, 7), __lsx_vsat_hu(tmp, 7));
+ return __lsx_vpickve2gr_w(v, 0);
+}
#elif defined __ARM_NEON__
Q_ALWAYS_INLINE uint toArgb32(uint16x4_t v)
{
@@ -201,6 +251,11 @@ Q_ALWAYS_INLINE uint toArgb32(QRgba64 rgba64)
__m128i v = _mm_loadl_epi64((const __m128i *)&rgba64);
v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(3, 0, 1, 2));
return toArgb32(v);
+#elif defined __loongarch_sx
+ __m128i v = __lsx_vilvl_d(__lsx_vldi(0), __lsx_vldrepl_d((const __m128i*)&rgba64, 0));
+ const __m128i shuffleMask = (__m128i)(v8i16){2, 1, 0, 3, 4, 5, 6, 7};
+ v = __lsx_vshuf_h(shuffleMask, __lsx_vldi(0), v);
+ return toArgb32(v);
#elif defined __ARM_NEON__
uint16x4_t v = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&rgba64)));
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -220,6 +275,9 @@ Q_ALWAYS_INLINE uint toRgba8888(QRgba64 rgba64)
#if defined __SSE2__
__m128i v = _mm_loadl_epi64((const __m128i *)&rgba64);
return toArgb32(v);
+#elif defined __loongarch_sx
+ __m128i v = __lsx_vilvl_d(__lsx_vldi(0), __lsx_vldrepl_d((const __m128i*)&rgba64, 0));
+ return toArgb32(v);
#elif defined __ARM_NEON__
uint16x4_t v = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&rgba64)));
return toArgb32(v);
@@ -248,6 +306,24 @@ inline QRgba64 rgbBlend(QRgba64 d, QRgba64 s, uint rgbAlpha)
vd = _mm_packs_epi32(vd, _mm_setzero_si128());
_mm_storel_epi64((__m128i *)&blend, vd);
+#elif defined(__loongarch_sx)
+ const __m128i zero = __lsx_vldi(0);
+ __m128i vd = __lsx_vilvl_d(zero, __lsx_vldrepl_d((const __m128i *)&d, 0));
+ __m128i vs = __lsx_vilvl_d(zero, __lsx_vldrepl_d((const __m128i *)&s, 0));
+ __m128i va = __lsx_vinsgr2vr_w(zero, rgbAlpha, 0);
+ va = __lsx_vilvl_b(va, va);
+ const __m128i shuffleMask = (__m128i)(v8i16){2, 1, 0, 3, 4, 5, 6, 7};
+ va = __lsx_vshuf_h(shuffleMask, zero, va);
+ __m128i vb = __lsx_vxor_v(__lsx_vreplgr2vr_h(-1), va);
+
+ vs = __lsx_vilvl_h(__lsx_vmuh_hu(vs, va), __lsx_vmul_h(vs, va));
+ vd = __lsx_vilvl_h(__lsx_vmuh_hu(vd, vb), __lsx_vmul_h(vd, vb));
+ vd = __lsx_vadd_w(vd, vs);
+ vd = __lsx_vadd_w(vd, __lsx_vsrli_w(vd, 16));
+ vd = __lsx_vadd_w(vd, __lsx_vreplgr2vr_w(0x8000));
+ vd = __lsx_vsrai_w(vd, 16);
+ vd = __lsx_vpickev_h(zero, __lsx_vsat_w(vd, 15));
+ __lsx_vstelm_d(vd, (__m128i *)&blend, 0, 0);
#elif defined(__ARM_NEON__)
uint16x4_t vd = vreinterpret_u16_u64(vmov_n_u64(d));
uint16x4_t vs = vreinterpret_u16_u64(vmov_n_u64(s));
保存上述 diff 为 simd_loongarch_support.patch
cd C:\src\qt5\qtbase
git apply simd_loongarch_support.patch
在 CMD 命令行窗口 中设置以下环境变量,这些变量将指导 configure 脚本找到正确的工具链和 SDK。
REM 确保您位于 Qt 源码的 qtbase 目录下
cd C:\src\qt5
REM 1. 设置 OpenHarmony SDK 路径 (请根据您的实际路径修改)
SET OHOS_SDK_PATH=C:\windows-ohos-sdk\12
REM 2. 设置 OpenHarmony SDK 的 sysroot 路径
SET OHOS_SDK_SYSROOT=%OHOS_SDK_PATH%\native\sysroot
REM 3. 设置 LLVM 工具链路径
SET LLVM_INSTALL_DIR=%OHOS_SDK_PATH%\native\llvm
REM 4. 设置要跳过的 Qt 模块,以加快编译速度和减小体积
SET QT_SKIPS=-skip qtactiveqt -skip qtandroidextras -skip qtcanvas3d -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsystems -skip qttools -skip qttranslations -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwinextras -skip qtx11extras -no-dbus
继续在同一个 CMD 窗口中执行以下命令。
oh-clang 交叉编译平台,并指定目标架构为 loongarch64。
mkdir build
cd build
..\configure.bat -xplatform oh-clang -device-option OHOS_ARCH=loongarch64 -release -opensource -confirm-license %QT_SKIPS% -nomake tests -nomake examples -prefix ./qtoh
configure 参数解析:
qtoh 文件夹中。mingw32-make 进行编译。为了利用多核 CPU 加快速度,可以使用 -j 参数。
REM 使用 %NUMBER_OF_PROCESSORS% 自动获取 CPU 核心数
mingw32-make -j%NUMBER_OF_PROCESSORS%
REM 或者手动指定核心数,例如 8 核
REM mingw32-make -j8
编译过程将花费较长时间,请耐心等待。
-prefix 指定的目录。
mingw32-make install
当 install 命令成功执行后,您将在 C:\src\qt5\build\qtoh 目录下找到为 OpenHarmony (LoongArch64) 编译好的 Qt SDK。该 SDK 包含了头文件、库文件和相关工具,可以用于后续的应用程序开发。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。