1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdrawhelper_arm_simd_p.h"
44 #include <private/qpaintengine_raster_p.h>
45 #include <private/qblendfunctions_p.h>
47 #ifdef QT_HAVE_ARM_SIMD
49 #if defined(Q_OS_SYMBIAN)
50 #if !defined(__SWITCH_TO_ARM)
53 #define __SWITCH_TO_ARM asm("push {r0} ");\
54 asm("add r0, pc, #4 ");\
59 asm("ldr r0, [sp], #4 ")
60 #define __END_ARM asm(".code 16 ")
62 #define __SWITCH_TO_ARM asm(".code 32 ");
66 #define __SWITCH_TO_ARM
68 #endif //__MARM_THUMB__
72 #if defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)
73 __asm void qt_blend_argb32_on_argb32_arm_simd(uchar *destPixels, int dbpl,
74 const uchar *srcPixels, int sbpl,
84 stmfd sp!, {r4-r12, r14}
86 // read arguments off the stack
90 // adjust dbpl and sbpl
96 // load 0xFF00FF00 to r12
100 // load 0x800080 to r14
117 cmp r6, #256 //test if we have fully opaque constant alpha value
118 bne argb32constalpha // branch if not
126 ldr r8, [r2], #4 // load src pixel
128 // Negate r8 and extract src alpha
129 mvn r11, r8 // bitwise not
130 uxtb r11, r11, ror #24
132 cmp r11, #0 // test for full src opacity (negated)
135 cmp r11, #255 // test for full src transparency (negated)
139 ldr r9, [r0] // load dst pixel
143 uxtb16 r6, r9, ror #8
144 mla r10, r11, r10, r14
146 uxtab16 r10, r10, r10, ror #8
147 uxtab16 r9, r9, r9, ror #8
149 uxtab16 r10, r9, r10, ror #8
160 bgt argb32_next_pixel
162 add r0, r0, r1 // dest = dest + dbpl
163 add r2, r2, r3 // src = src + sbpl
173 beq argb32_blend_exit
175 ; const_alpha = (const_alpha * 255) >> 8;
180 argb32constalpha_next_row
184 argb32constalpha_next_pixel
186 ldr r9, [r2], #4 // load src pixel
190 uxtb16 r6, r9, ror #8
191 mla r10, r11, r10, r14
193 uxtab16 r10, r10, r10, ror #8
194 uxtab16 r9, r9, r9, ror #8
196 uxtab16 r8, r9, r10, ror #8
198 ldr r9, [r0] // load dst pixel
202 uxtb16 r6, r9, ror #8
204 // Negate r8 and extract src alpha
205 mvn r9, r8 // bitwise not
208 mla r10, r9, r10, r14
210 uxtab16 r10, r10, r10, ror #8
211 uxtab16 r9, r9, r9, ror #8
213 uxtab16 r10, r9, r10, ror #8
220 bgt argb32constalpha_next_pixel
222 add r0, r0, r1 // dest = dest + dbpl
223 add r2, r2, r3 // src = src + sbpl
226 bgt argb32constalpha_next_row
231 ldmfd sp!, {r4-r12, lr}
237 void qt_blend_rgb32_on_rgb32_arm_simd(uchar *destPixels, int dbpl,
238 const uchar *srcPixels, int sbpl,
242 if (const_alpha != 256) {
243 qt_blend_argb32_on_argb32_arm_simd(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
247 const uint *src = (const uint *) srcPixels;
248 uint *dst = (uint *) destPixels;
250 for (int y=0; y<h; ++y) {
251 qt_memconvert(dst, src, w);
252 dst = (quint32 *)(((uchar *) dst) + dbpl);
253 src = (const quint32 *)(((const uchar *) src) + sbpl);
257 for (int y=0; y<h; ++y) {
258 memcpy(dst, src, len);
259 dst = (quint32 *)(((uchar *) dst) + dbpl);
260 src = (const quint32 *)(((const uchar *) src) + sbpl);
265 #else // defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)
267 // TODO: add GNU assembler instructions and support for other platforms.
268 // Default to C code for now
270 void qt_blend_argb32_on_argb32_arm_simd(uchar *destPixels, int dbpl,
271 const uchar *srcPixels, int sbpl,
275 const uint *src = (const uint *) srcPixels;
276 uint *dst = (uint *) destPixels;
277 if (const_alpha == 256) {
278 for (int y=0; y<h; ++y) {
279 for (int x=0; x<w; ++x) {
284 dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
286 dst = (quint32 *)(((uchar *) dst) + dbpl);
287 src = (const quint32 *)(((const uchar *) src) + sbpl);
289 } else if (const_alpha != 0) {
290 const_alpha = (const_alpha * 255) >> 8;
291 for (int y=0; y<h; ++y) {
292 for (int x=0; x<w; ++x) {
293 uint s = BYTE_MUL(src[x], const_alpha);
294 dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
296 dst = (quint32 *)(((uchar *) dst) + dbpl);
297 src = (const quint32 *)(((const uchar *) src) + sbpl);
302 void qt_blend_rgb32_on_rgb32_arm_simd(uchar *destPixels, int dbpl,
303 const uchar *srcPixels, int sbpl,
307 if (const_alpha != 256) {
308 qt_blend_argb32_on_argb32_arm_simd(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
312 const uint *src = (const uint *) srcPixels;
313 uint *dst = (uint *) destPixels;
315 for (int y=0; y<h; ++y) {
316 qt_memconvert(dst, src, w);
317 dst = (quint32 *)(((uchar *) dst) + dbpl);
318 src = (const quint32 *)(((const uchar *) src) + sbpl);
322 for (int y=0; y<h; ++y) {
323 memcpy(dst, src, len);
324 dst = (quint32 *)(((uchar *) dst) + dbpl);
325 src = (const quint32 *)(((const uchar *) src) + sbpl);
332 #endif // QT_HAVE_ARMV_SIMD