diff options
Diffstat (limited to 'src/gui/painting')
-rw-r--r-- | src/gui/painting/painting.pri | 164 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 144 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon_asm.S | 105 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon_p.h | 3 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_sse2.cpp | 168 | ||||
-rw-r--r-- | src/gui/painting/qdrawingprimitive_sse2_p.h | 222 | ||||
-rw-r--r-- | src/gui/painting/qgraphicssystem.cpp | 4 | ||||
-rw-r--r-- | src/gui/painting/qgraphicssystem_runtime.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qgraphicssystem_runtime_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qmemrotate.cpp | 51 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 24 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 9 |
14 files changed, 559 insertions, 347 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index a5cfb84..4023f65 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -202,154 +202,17 @@ x11|embedded { DEFINES += QT_NO_CUPS QT_NO_LPR } -contains(QMAKE_MAC_XARCH, no) { - DEFINES += QT_NO_MAC_XARCH -} else:if(mmx|3dnow|sse|sse2|iwmmxt) { +if(mmx|3dnow|sse|sse2|iwmmxt) { HEADERS += painting/qdrawhelper_x86_p.h \ painting/qdrawhelper_mmx_p.h \ - painting/qdrawhelper_sse_p.h - mmx { - DEFINES += QT_HAVE_MMX - MMX_SOURCES += painting/qdrawhelper_mmx.cpp - } - 3dnow { - DEFINES += QT_HAVE_3DNOW - MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp - sse { - SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp - } - } - sse { - DEFINES += QT_HAVE_SSE - SSE_SOURCES += painting/qdrawhelper_sse.cpp - - DEFINES += QT_HAVE_MMXEXT - } - sse2 { - DEFINES += QT_HAVE_SSE2 - SSE2_SOURCES += painting/qdrawhelper_sse2.cpp - } - iwmmxt { - DEFINES += QT_HAVE_IWMMXT - IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp - } - - win32-g++*|!win32:!*-icc* { - mmx { - mmx_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx_compiler.commands += -Xarch_i386 -mmmx - mmx_compiler.commands += -Xarch_x86_64 -mmmx - } else { - mmx_compiler.commands += -mmmx - } - - mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx_compiler.dependency_type = TYPE_C - mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx_compiler.input = MMX_SOURCES - mmx_compiler.variable_out = OBJECTS - mmx_compiler.name = compiling[mmx] ${QMAKE_FILE_IN} - silent:mmx_compiler.commands = @echo compiling[mmx] ${QMAKE_FILE_IN} && $$mmx_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx_compiler - } - 3dnow { - mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx - mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx - } else { - mmx3dnow_compiler.commands += -m3dnow -mmmx - } - - mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - mmx3dnow_compiler.dependency_type = TYPE_C - mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - mmx3dnow_compiler.input = MMX3DNOW_SOURCES - mmx3dnow_compiler.variable_out = OBJECTS - mmx3dnow_compiler.name = compiling[mmx3dnow] ${QMAKE_FILE_IN} - silent:mmx3dnow_compiler.commands = @echo compiling[mmx3dnow] ${QMAKE_FILE_IN} && $$mmx3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler - sse { - sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse - sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse - } else { - sse3dnow_compiler.commands += -m3dnow -msse - } - - sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse3dnow_compiler.dependency_type = TYPE_C - sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse3dnow_compiler.input = SSE3DNOW_SOURCES - sse3dnow_compiler.variable_out = OBJECTS - sse3dnow_compiler.name = compiling[sse3dnow] ${QMAKE_FILE_IN} - silent:sse3dnow_compiler.commands = @echo compiling[sse3dnow] ${QMAKE_FILE_IN} && $$sse3dnow_compiler.commands - QMAKE_EXTRA_COMPILERS += sse3dnow_compiler - } - } - sse { - sse_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse_compiler.commands += -Xarch_i386 -msse - sse_compiler.commands += -Xarch_x86_64 -msse - } else { - sse_compiler.commands += -msse - } - - sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse_compiler.dependency_type = TYPE_C - sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse_compiler.input = SSE_SOURCES - sse_compiler.variable_out = OBJECTS - sse_compiler.name = compiling[sse] ${QMAKE_FILE_IN} - silent:sse_compiler.commands = @echo compiling[sse] ${QMAKE_FILE_IN} && $$sse_compiler.commands - QMAKE_EXTRA_COMPILERS += sse_compiler - } - sse2 { - sse2_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - sse2_compiler.commands += -Xarch_i386 -msse2 - sse2_compiler.commands += -Xarch_x86_64 -msse2 - } else { - sse2_compiler.commands += -msse2 - } - - sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - sse2_compiler.dependency_type = TYPE_C - sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - sse2_compiler.input = SSE2_SOURCES - sse2_compiler.variable_out = OBJECTS - sse2_compiler.name = compiling[sse2] ${QMAKE_FILE_IN} - silent:sse2_compiler.commands = @echo compiling[sse2] ${QMAKE_FILE_IN} && $$sse2_compiler.commands - QMAKE_EXTRA_COMPILERS += sse2_compiler - } - iwmmxt { - iwmmxt_compiler.commands = $$QMAKE_CXX -c -Winline - iwmmxt_compiler.commands += -mcpu=iwmmxt - iwmmxt_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} - iwmmxt_compiler.dependency_type = TYPE_C - iwmmxt_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - iwmmxt_compiler.input = IWMMXT_SOURCES - iwmmxt_compiler.variable_out = OBJECTS - iwmmxt_compiler.name = compiling[iwmmxt] ${QMAKE_FILE_IN} - silent:iwmmxt_compiler.commands = @echo compiling[iwmmxt] ${QMAKE_FILE_IN} && $$iwmmxt_compiler.commands - QMAKE_EXTRA_COMPILERS += iwmmxt_compiler - } - } else { - mmx: SOURCES += $$MMX_SOURCES - 3dnow: SOURCES += $$MMX3DNOW_SOURCES - 3dnow:sse: SOURCES += $$SSE3DNOW_SOURCES - sse: SOURCES += $$SSE_SOURCES - sse2: SOURCES += $$SSE2_SOURCES - iwmmxt: SOURCES += $$IWMMXT_SOURCES - } + painting/qdrawhelper_sse_p.h \ + painting/qdrawingprimitive_sse2_p.h + MMX_SOURCES += painting/qdrawhelper_mmx.cpp + MMX3DNOW_SOURCES += painting/qdrawhelper_mmx3dnow.cpp + SSE3DNOW_SOURCES += painting/qdrawhelper_sse3dnow.cpp + SSE_SOURCES += painting/qdrawhelper_sse.cpp + SSE2_SOURCES += painting/qdrawhelper_sse2.cpp + IWMMXT_SOURCES += painting/qdrawhelper_iwmmxt.cpp } x11 { @@ -402,11 +265,4 @@ neon:*-g++* { QMAKE_EXTRA_COMPILERS += neon_compiler } -contains(QT_CONFIG, zlib) { - INCLUDEPATH += ../3rdparty/zlib -} else:!contains(QT_CONFIG, no-zlib) { - symbian:LIBS_PRIVATE += -llibz - else:if(unix|win32-g++*):LIBS_PRIVATE += -lz - else:LIBS += zdll.lib -} - +include($$PWD/../../3rdparty/zlib_dependency.pri) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 5727b3c..ca9556b 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5014,7 +5014,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * length -= copy_image_width; copy_image_width *= 2; } - qt_memconvert(dest, src, length); + if (length > 0) + qt_memconvert(dest, src, length); } else { while (length) { int l = qMin(image_width - sx, length); @@ -7901,6 +7902,9 @@ void qInitDrawhelperAsm() functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; + + qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon; + qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon; } #endif diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 3ce90d2..03fe075 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -622,6 +622,150 @@ void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, u } } +static const int tileSize = 32; + +extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count); + +void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sstride, uchar *destPixels, int dstride) +{ + const ushort *src = (const ushort *)srcPixels; + ushort *dest = (ushort *)destPixels; + + sstride /= sizeof(ushort); + dstride /= sizeof(ushort); + + const int pack = sizeof(quint32) / sizeof(ushort); + const int unaligned = + qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h)); + const int restX = w % tileSize; + const int restY = (h - unaligned) % tileSize; + const int unoptimizedY = restY % pack; + const int numTilesX = w / tileSize + (restX > 0); + const int numTilesY = (h - unaligned) / tileSize + (restY >= pack); + + for (int tx = 0; tx < numTilesX; ++tx) { + const int startx = w - tx * tileSize - 1; + const int stopx = qMax(startx - tileSize, 0); + + if (unaligned) { + for (int x = startx; x >= stopx; --x) { + ushort *d = dest + (w - x - 1) * dstride; + for (int y = 0; y < unaligned; ++y) { + *d++ = src[y * sstride + x]; + } + } + } + + for (int ty = 0; ty < numTilesY; ++ty) { + const int starty = ty * tileSize + unaligned; + const int stopy = qMin(starty + tileSize, h - unoptimizedY); + + int x = startx; + // qt_rotate90_16_neon writes to eight rows, four pixels at a time + for (; x >= stopx + 7; x -= 8) { + ushort *d = dest + (w - x - 1) * dstride + starty; + const ushort *s = &src[starty * sstride + x - 7]; + qt_rotate90_16_neon(d, s, sstride * 2, dstride * 2, stopy - starty); + } + + for (; x >= stopx; --x) { + quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty); + for (int y = starty; y < stopy; y += pack) { + quint32 c = src[y * sstride + x]; + for (int i = 1; i < pack; ++i) { + const int shift = (sizeof(int) * 8 / pack * i); + const ushort color = src[(y + i) * sstride + x]; + c |= color << shift; + } + *d++ = c; + } + } + } + + if (unoptimizedY) { + const int starty = h - unoptimizedY; + for (int x = startx; x >= stopx; --x) { + ushort *d = dest + (w - x - 1) * dstride + starty; + for (int y = starty; y < h; ++y) { + *d++ = src[y * sstride + x]; + } + } + } + } +} + +extern "C" void qt_rotate270_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count); + +void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, + int sstride, + uchar *destPixels, int dstride) +{ + const ushort *src = (const ushort *)srcPixels; + ushort *dest = (ushort *)destPixels; + + sstride /= sizeof(ushort); + dstride /= sizeof(ushort); + + const int pack = sizeof(quint32) / sizeof(ushort); + const int unaligned = + qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h)); + const int restX = w % tileSize; + const int restY = (h - unaligned) % tileSize; + const int unoptimizedY = restY % pack; + const int numTilesX = w / tileSize + (restX > 0); + const int numTilesY = (h - unaligned) / tileSize + (restY >= pack); + + for (int tx = 0; tx < numTilesX; ++tx) { + const int startx = tx * tileSize; + const int stopx = qMin(startx + tileSize, w); + + if (unaligned) { + for (int x = startx; x < stopx; ++x) { + ushort *d = dest + x * dstride; + for (int y = h - 1; y >= h - unaligned; --y) { + *d++ = src[y * sstride + x]; + } + } + } + + for (int ty = 0; ty < numTilesY; ++ty) { + const int starty = h - 1 - unaligned - ty * tileSize; + const int stopy = qMax(starty - tileSize, unoptimizedY); + + int x = startx; + // qt_rotate90_16_neon writes to eight rows, four pixels at a time + for (; x < stopx - 7; x += 8) { + ushort *d = dest + x * dstride + h - 1 - starty; + const ushort *s = &src[starty * sstride + x]; + qt_rotate90_16_neon(d + 7 * dstride, s, -sstride * 2, -dstride * 2, starty - stopy); + } + + for (; x < stopx; ++x) { + quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride + + h - 1 - starty); + for (int y = starty; y > stopy; y -= pack) { + quint32 c = src[y * sstride + x]; + for (int i = 1; i < pack; ++i) { + const int shift = (sizeof(int) * 8 / pack * i); + const ushort color = src[(y - i) * sstride + x]; + c |= color << shift; + } + *d++ = c; + } + } + } + if (unoptimizedY) { + const int starty = unoptimizedY - 1; + for (int x = startx; x < stopx; ++x) { + ushort *d = dest + x * dstride + h - 1 - starty; + for (int y = starty; y >= 0; --y) { + *d++ = src[y * sstride + x]; + } + } + } + } +} + QT_END_NAMESPACE #endif // QT_HAVE_NEON diff --git a/src/gui/painting/qdrawhelper_neon_asm.S b/src/gui/painting/qdrawhelper_neon_asm.S index 9992817..d9cdc36 100644 --- a/src/gui/painting/qdrawhelper_neon_asm.S +++ b/src/gui/painting/qdrawhelper_neon_asm.S @@ -190,3 +190,108 @@ blend_8_pixels_rgb16_on_rgb16_neon: bx lr .endfunc + +/* void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count) */ + .func qt_rotate90_16_neon + .global qt_rotate90_16_neon + /* For ELF format also set function visibility to hidden */ +#ifdef __ELF__ + .hidden qt_rotate90_16_neon + .type qt_rotate90_16_neon, %function +#endif +qt_rotate90_16_neon: + push { r4-r11, lr } + ldr r5, [sp, #(9*4)] + + /* The preloads are the key to getting good performance */ + pld [r1] + + mov r4, r5, asr #2 + add r6, r0, r3 + add r7, r6, r3 + + add r8, r7, r3 + add r9, r8, r3 + + pld [r1, r2] + + add r10, r9, r3 + add r11, r10, r3 + + add r3, r3, r11 + and r5, r5, #3 + + pld [r1, r2, lsl #1] + + cmp r4, #0 + beq .rotate90_16_tail + +.rotate90_16_loop: + vld1.16 { q8 }, [r1], r2 + + pld [r1, r2, lsl #1] + + vld1.16 { q9 }, [r1], r2 + vld1.16 { q10 }, [r1], r2 + vld1.16 { q11 }, [r1], r2 + + pld [r1] + + /* Could have used four quad-word zips instead, + but those take three cycles as opposed to one. */ + vzip.16 d16, d20 + vzip.16 d17, d21 + + vzip.16 d18, d22 + + pld [r1, r2] + + vzip.16 d19, d23 + + vzip.16 d16, d18 + vzip.16 d17, d19 + + pld [r1, r2, lsl #1] + + vzip.16 d20, d22 + vzip.16 d21, d23 + + vst1.16 { d23 }, [r0]! + vst1.16 { d21 }, [r6]! + vst1.16 { d19 }, [r7]! + vst1.16 { d17 }, [r8]! + vst1.16 { d22 }, [r9]! + vst1.16 { d20 }, [r10]! + vst1.16 { d18 }, [r11]! + vst1.16 { d16 }, [r3]! + + sub r4, r4, #1 + cmp r4, #0 + bne .rotate90_16_loop + b .rotate90_16_tail + +.rotate90_16_tail_loop: + sub r5, r5, #2 + + vld1.16 { q8 }, [r1], r2 + vld1.16 { q9 }, [r1], r2 + + vzip.16 d16, d18 + vzip.16 d17, d19 + + vst1.32 { d19[1] }, [r0]! + vst1.32 { d19[0] }, [r6]! + vst1.32 { d17[1] }, [r7]! + vst1.32 { d17[0] }, [r8]! + vst1.32 { d18[1] }, [r9]! + vst1.32 { d18[0] }, [r10]! + vst1.32 { d16[1] }, [r11]! + vst1.32 { d16[0] }, [r3]! + +.rotate90_16_tail: + cmp r5, #0 + bgt .rotate90_16_tail_loop + + pop { r4-r11, pc } + + .endfunc diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index c054a1e..cd2dbfc 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -120,6 +120,9 @@ void qt_transform_image_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, const QTransform &targetRectTransform, int const_alpha); +void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); +void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); + uint * QT_FASTCALL qt_destFetchRGB16_neon(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index acf765c..97c78bb 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -152,6 +152,7 @@ typedef void (*SrcOverTransformFunc)(uchar *destPixels, int dbpl, const QTransform &targetRectTransform, int const_alpha); +typedef void (*MemRotateFunc)(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl); struct DrawHelper { ProcessSpans blendColor; @@ -165,6 +166,7 @@ struct DrawHelper { extern SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats]; extern SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats]; +extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 6cd8688..346e177 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -43,176 +43,12 @@ #ifdef QT_HAVE_SSE2 +#include <private/qsimd_p.h> +#include <private/qdrawingprimitive_sse2_p.h> #include <private/qpaintengine_raster_p.h> -#ifdef QT_LINUXBASE -// this is an evil hack - the posix_memalign declaration in LSB -// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 -# define posix_memalign _lsb_hack_posix_memalign -# include <emmintrin.h> -# undef posix_memalign -#else -# include <emmintrin.h> -#endif - QT_BEGIN_NAMESPACE -/* - * Multiply the components of pixelVector by alphaChannel - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ -{ \ - /* 1. separate the colors in 2 vectors so each color is on 16 bits \ - (in order to be multiplied by the alpha \ - each 32 bit of dstVectorAG are in the form 0x00AA00GG \ - each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ - __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ - __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ - \ - /* 2. multiply the vectors by the alpha channel */\ - pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ - pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ - \ - /* 3. devide by 255, that's the tricky part. \ - we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ - /** so first (X + X/256 + rounding) */\ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ - pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ - pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ - \ - /** second devide by 256 */\ - pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ - /** for AG, we could >> 8 to divide followed by << 8 to put the \ - bytes in the correct position. By masking instead, we execute \ - only one instruction */\ - pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ - \ - /* 4. combine the 2 pairs of colors */ \ - result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ -} - -/* - * Each 32bits components of alphaChannel must be in the form 0x00AA00AA - * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component - * colorMask must have 0x00ff00ff on each 32 bits component - * half must have the value 128 (0x80) for each 32 bits compnent - */ -#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ - /* interpolate AG */\ - __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ - __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ - __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ - __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ - __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ - finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ - finalAG = _mm_add_epi16(finalAG, half); \ - finalAG = _mm_andnot_si128(colorMask, finalAG); \ - \ - /* interpolate RB */\ - __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ - __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ - __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ - __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ - __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ - finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ - finalRB = _mm_add_epi16(finalRB, half); \ - finalRB = _mm_srli_epi16(finalRB, 8); \ - \ - /* combine */\ - result = _mm_or_si128(finalAG, finalRB); \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -//const __m128i alphaMask = _mm_set1_epi32(0xff000000); -// -// The computation being done is: -// result = s + d * (1-alpha) -// with shortcuts if fully opaque or fully transparent. -#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ - /* all opaque */ \ - _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ - } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ - /* not fully transparent */ \ - /* extract the alpha channel on 2 x 16 bits */ \ - /* so we have room for the multiplication */ \ - /* each 32 bits will be in the form 0x00AA00AA */ \ - /* with A being the 1 - alpha */ \ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - /* result = s + d * (1-alpha) */\ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - uint s = src[x]; \ - if (s >= 0xff000000) \ - dst[x] = s; \ - else if (s != 0) \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ -} - -// Basically blend src over dst with the const alpha defined as constAlphaVector. -// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: -//const __m128i nullVector = _mm_set1_epi32(0); -//const __m128i half = _mm_set1_epi16(0x80); -//const __m128i one = _mm_set1_epi16(0xff); -//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); -// -// The computation being done is: -// dest = (s + d * sia) * ca + d * cia -// = s * ca + d * (sia * ca + cia) -// = s * ca + d * (1 - sa*ca) -#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ -{ \ - int x = 0; \ - for (; x < length-3; x += 4) { \ - __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ - if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ - BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ -\ - __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ - alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ - alphaChannel = _mm_sub_epi16(one, alphaChannel); \ - \ - const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ - __m128i destMultipliedByOneMinusAlpha; \ - BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ - \ - const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ - _mm_storeu_si128((__m128i *)&dst[x], result); \ - } \ - } \ - for (; x < length; ++x) { \ - quint32 s = src[x]; \ - if (s != 0) { \ - s = BYTE_MUL(s, const_alpha); \ - dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ - } \ - } \ -} - void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h new file mode 100644 index 0000000..3c96946 --- /dev/null +++ b/src/gui/painting/qdrawingprimitive_sse2_p.h @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRAWINGPRIMITIVE_SSE2_P_H +#define QDRAWINGPRIMITIVE_SSE2_P_H + +#include <private/qsimd_p.h> + +#ifdef QT_HAVE_SSE2 + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +/* + * Multiply the components of pixelVector by alphaChannel + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \ +{ \ + /* 1. separate the colors in 2 vectors so each color is on 16 bits \ + (in order to be multiplied by the alpha \ + each 32 bit of dstVectorAG are in the form 0x00AA00GG \ + each 32 bit of dstVectorRB are in the form 0x00RR00BB */\ + __m128i pixelVectorAG = _mm_srli_epi16(pixelVector, 8); \ + __m128i pixelVectorRB = _mm_and_si128(pixelVector, colorMask); \ + \ + /* 2. multiply the vectors by the alpha channel */\ + pixelVectorAG = _mm_mullo_epi16(pixelVectorAG, alphaChannel); \ + pixelVectorRB = _mm_mullo_epi16(pixelVectorRB, alphaChannel); \ + \ + /* 3. devide by 255, that's the tricky part. \ + we do it like for BYTE_MUL(), with bit shift: X/255 ~= (X + X/256 + rounding)/256 */ \ + /** so first (X + X/256 + rounding) */\ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, _mm_srli_epi16(pixelVectorRB, 8)); \ + pixelVectorRB = _mm_add_epi16(pixelVectorRB, half); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, _mm_srli_epi16(pixelVectorAG, 8)); \ + pixelVectorAG = _mm_add_epi16(pixelVectorAG, half); \ + \ + /** second devide by 256 */\ + pixelVectorRB = _mm_srli_epi16(pixelVectorRB, 8); \ + /** for AG, we could >> 8 to divide followed by << 8 to put the \ + bytes in the correct position. By masking instead, we execute \ + only one instruction */\ + pixelVectorAG = _mm_andnot_si128(colorMask, pixelVectorAG); \ + \ + /* 4. combine the 2 pairs of colors */ \ + result = _mm_or_si128(pixelVectorAG, pixelVectorRB); \ +} + +/* + * Each 32bits components of alphaChannel must be in the form 0x00AA00AA + * oneMinusAlphaChannel must be 255 - alpha for each 32 bits component + * colorMask must have 0x00ff00ff on each 32 bits component + * half must have the value 128 (0x80) for each 32 bits compnent + */ +#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \ + /* interpolate AG */\ + __m128i srcVectorAG = _mm_srli_epi16(srcVector, 8); \ + __m128i dstVectorAG = _mm_srli_epi16(dstVector, 8); \ + __m128i srcVectorAGalpha = _mm_mullo_epi16(srcVectorAG, alphaChannel); \ + __m128i dstVectorAGoneMinusAlphalpha = _mm_mullo_epi16(dstVectorAG, oneMinusAlphaChannel); \ + __m128i finalAG = _mm_add_epi16(srcVectorAGalpha, dstVectorAGoneMinusAlphalpha); \ + finalAG = _mm_add_epi16(finalAG, _mm_srli_epi16(finalAG, 8)); \ + finalAG = _mm_add_epi16(finalAG, half); \ + finalAG = _mm_andnot_si128(colorMask, finalAG); \ + \ + /* interpolate RB */\ + __m128i srcVectorRB = _mm_and_si128(srcVector, colorMask); \ + __m128i dstVectorRB = _mm_and_si128(dstVector, colorMask); \ + __m128i srcVectorRBalpha = _mm_mullo_epi16(srcVectorRB, alphaChannel); \ + __m128i dstVectorRBoneMinusAlphalpha = _mm_mullo_epi16(dstVectorRB, oneMinusAlphaChannel); \ + __m128i finalRB = _mm_add_epi16(srcVectorRBalpha, dstVectorRBoneMinusAlphalpha); \ + finalRB = _mm_add_epi16(finalRB, _mm_srli_epi16(finalRB, 8)); \ + finalRB = _mm_add_epi16(finalRB, half); \ + finalRB = _mm_srli_epi16(finalRB, 8); \ + \ + /* combine */\ + result = _mm_or_si128(finalAG, finalRB); \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +//const __m128i alphaMask = _mm_set1_epi32(0xff000000); +// +// The computation being done is: +// result = s + d * (1-alpha) +// with shortcuts if fully opaque or fully transparent. +#define BLEND_SOURCE_OVER_ARGB32_SSE2(dst, src, length, nullVector, half, one, colorMask, alphaMask) { \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + const __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + const __m128i srcVectorAlpha = _mm_and_si128(srcVector, alphaMask); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, alphaMask)) == 0xffff) { \ + /* all opaque */ \ + _mm_storeu_si128((__m128i *)&dst[x], srcVector); \ + } else if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVectorAlpha, nullVector)) != 0xffff) { \ + /* not fully transparent */ \ + /* extract the alpha channel on 2 x 16 bits */ \ + /* so we have room for the multiplication */ \ + /* each 32 bits will be in the form 0x00AA00AA */ \ + /* with A being the 1 - alpha */ \ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + /* result = s + d * (1-alpha) */\ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + uint s = src[x]; \ + if (s >= 0xff000000) \ + dst[x] = s; \ + else if (s != 0) \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ +} + +// Basically blend src over dst with the const alpha defined as constAlphaVector. +// nullVector, half, one, colorMask are constant accross the whole image/texture, and should be defined as: +//const __m128i nullVector = _mm_set1_epi32(0); +//const __m128i half = _mm_set1_epi16(0x80); +//const __m128i one = _mm_set1_epi16(0xff); +//const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); +// +// The computation being done is: +// dest = (s + d * sia) * ca + d * cia +// = s * ca + d * (sia * ca + cia) +// = s * ca + d * (1 - sa*ca) +#define BLEND_SOURCE_OVER_ARGB32_WITH_CONST_ALPHA_SSE2(dst, src, length, nullVector, half, one, colorMask, constAlphaVector) \ +{ \ + int x = 0; \ + for (; x < length-3; x += 4) { \ + __m128i srcVector = _mm_loadu_si128((__m128i *)&src[x]); \ + if (_mm_movemask_epi8(_mm_cmpeq_epi32(srcVector, nullVector)) != 0xffff) { \ + BYTE_MUL_SSE2(srcVector, srcVector, constAlphaVector, colorMask, half); \ +\ + __m128i alphaChannel = _mm_srli_epi32(srcVector, 24); \ + alphaChannel = _mm_or_si128(alphaChannel, _mm_slli_epi32(alphaChannel, 16)); \ + alphaChannel = _mm_sub_epi16(one, alphaChannel); \ + \ + const __m128i dstVector = _mm_loadu_si128((__m128i *)&dst[x]); \ + __m128i destMultipliedByOneMinusAlpha; \ + BYTE_MUL_SSE2(destMultipliedByOneMinusAlpha, dstVector, alphaChannel, colorMask, half); \ + \ + const __m128i result = _mm_add_epi8(srcVector, destMultipliedByOneMinusAlpha); \ + _mm_storeu_si128((__m128i *)&dst[x], result); \ + } \ + } \ + for (; x < length; ++x) { \ + quint32 s = src[x]; \ + if (s != 0) { \ + s = BYTE_MUL(s, const_alpha); \ + dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s)); \ + } \ + } \ +} + +QT_END_NAMESPACE + +#endif // QT_HAVE_SSE2 + +#endif // QDRAWINGPRIMITIVE_SSE2_P_H diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index 69ce47e..f06e309 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -50,7 +50,7 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif -#ifdef Q_WS_S60 +#ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> #endif @@ -71,7 +71,7 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); -#elif defined(Q_WS_S60) +#elif defined(Q_OS_SYMBIAN) return new QS60PixmapData(type); #elif !defined(Q_WS_QWS) #error QGraphicsSystem::createDefaultPixmapData() not implemented diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 1c3ae10..3438137 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -418,7 +418,7 @@ void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name) QRuntimePixmapData *proxy = m_pixmapDatas.at(i); QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data); // ### TODO Optimize. Openvg and s60raster graphics systems could switch internal ARGB32_PRE QImage buffers. - newData->fromImage(proxy->m_data->toImage(), Qt::AutoColor | Qt::OrderedAlphaDither); + newData->fromImage(proxy->m_data->toImage(), Qt::NoOpaqueDetection); delete proxy->m_data; proxy->m_data = newData; proxy->readBackInfo(); diff --git a/src/gui/painting/qgraphicssystem_runtime_p.h b/src/gui/painting/qgraphicssystem_runtime_p.h index 101a8e7..7aab89c 100644 --- a/src/gui/painting/qgraphicssystem_runtime_p.h +++ b/src/gui/painting/qgraphicssystem_runtime_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QRuntimeGraphicsSystem; -class QRuntimePixmapData : public QPixmapData { +class Q_GUI_EXPORT QRuntimePixmapData : public QPixmapData { public: QRuntimePixmapData(const QRuntimeGraphicsSystem *gs, PixelType type); ~QRuntimePixmapData(); diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp index c37aa51..6888bb0 100644 --- a/src/gui/painting/qmemrotate.cpp +++ b/src/gui/painting/qmemrotate.cpp @@ -594,4 +594,55 @@ void Q_GUI_EXPORT qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHei qt_memrotate90_template(src, srcWidth, srcHeight, srcStride, reinterpret_cast<qrgb_gl_rgba *>(dest), dstStride); } +void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate90((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl); +} + +void qt_memrotate180_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate180((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl); +} + +void qt_memrotate270_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate270((const ushort *)srcPixels, w, h, sbpl, (ushort *)destPixels, dbpl); +} + +void qt_memrotate90_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate90((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl); +} + +void qt_memrotate180_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate180((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl); +} + +void qt_memrotate270_32(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) +{ + qt_memrotate270((const uint *)srcPixels, w, h, sbpl, (uint *)destPixels, dbpl); +} + +MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3] = +// 90, 180, 270 +{ + { 0, 0, 0 }, // Format_Invalid, + { 0, 0, 0 }, // Format_Mono, + { 0, 0, 0 }, // Format_MonoLSB, + { 0, 0, 0 }, // Format_Indexed8, + { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_RGB32, + { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_ARGB32, + { qt_memrotate90_32, qt_memrotate180_32, qt_memrotate270_32 }, // Format_ARGB32_Premultiplied, + { qt_memrotate90_16, qt_memrotate180_16, qt_memrotate270_16 }, // Format_RGB16, + { 0, 0, 0 }, // Format_ARGB8565_Premultiplied, + { 0, 0, 0 }, // Format_RGB666, + { 0, 0, 0 }, // Format_ARGB6666_Premultiplied, + { 0, 0, 0 }, // Format_RGB555, + { 0, 0, 0 }, // Format_ARGB8555_Premultiplied, + { 0, 0, 0 }, // Format_RGB888, + { 0, 0, 0 }, // Format_RGB444, + { 0, 0, 0 } // Format_ARGB4444_Premultiplied, +}; + QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 84b36c7..09a87aa 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2553,23 +2553,6 @@ namespace { return NoRotation; } - template <typename T> void memRotate(RotationType type, const T *srcBase, int w, int h, int sbpl, T *dstBase, int dbpl) - { - switch (type) { - case Rotation90: - qt_memrotate90(srcBase, w, h, sbpl, dstBase, dbpl); - break; - case Rotation180: - qt_memrotate180(srcBase, w, h, sbpl, dstBase, dbpl); - break; - case Rotation270: - qt_memrotate270(srcBase, w, h, sbpl, dstBase, dbpl); - break; - case NoRotation: - break; - } - } - inline bool isPixelAligned(const QRectF &rect) { return QRectF(rect.toRect()) == rect; } @@ -2650,7 +2633,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe { RotationType rotationType = qRotationType(s->matrix); - if (rotationType != NoRotation && img.rect().contains(sr.toAlignedRect())) { + if (rotationType != NoRotation && qMemRotateFunctions[d->rasterBuffer->format][rotationType] && img.rect().contains(sr.toAlignedRect())) { QRectF transformedTargetRect = s->matrix.mapRect(r); if ((!(s->renderHints & QPainter::SmoothPixmapTransform) && !(s->renderHints & QPainter::Antialiasing)) @@ -2678,10 +2661,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe uint cw = clippedSourceRect.width(); uint ch = clippedSourceRect.height(); - if (d->rasterBuffer->format == QImage::Format_RGB16) - memRotate(rotationType, (quint16 *)srcBase, cw, ch, sbpl, (quint16 *)dstBase, dbpl); - else - memRotate(rotationType, (quint32 *)srcBase, cw, ch, sbpl, (quint32 *)dstBase, dbpl); + qMemRotateFunctions[d->rasterBuffer->format][rotationType](srcBase, cw, ch, sbpl, dstBase, dbpl); return; } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 2ea6673..9dadbd5 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -8969,6 +8969,15 @@ void QPainter::drawPixmapFragments(const PixmapFragment *fragments, int fragment if (!d->engine) return; +#ifndef QT_NO_DEBUG + for (int i = 0; i < fragmentCount; ++i) { + QRectF sourceRect(fragments[i].sourceLeft, fragments[i].sourceTop, + fragments[i].width, fragments[i].height); + if (!(QRectF(pixmap.rect()).contains(sourceRect))) + qWarning("QPainter::drawPixmapFragments - the source rect is not contained by the pixmap's rectangle"); + } +#endif + if (d->engine->isExtended()) { d->extended->drawPixmapFragments(fragments, fragmentCount, pixmap, hints); } else { |