src/gui/painting/qdrawhelper.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    44 #include <private/qpainter_p.h>
    44 #include <private/qpainter_p.h>
    45 #include <private/qdrawhelper_x86_p.h>
    45 #include <private/qdrawhelper_x86_p.h>
    46 #include <private/qdrawhelper_armv6_p.h>
    46 #include <private/qdrawhelper_armv6_p.h>
    47 #include <private/qdrawhelper_neon_p.h>
    47 #include <private/qdrawhelper_neon_p.h>
    48 #include <private/qmath_p.h>
    48 #include <private/qmath_p.h>
       
    49 #include <private/qsimd_p.h>
    49 #include <qmath.h>
    50 #include <qmath.h>
    50 
    51 
    51 QT_BEGIN_NAMESPACE
    52 QT_BEGIN_NAMESPACE
    52 
    53 
    53 
    54 
    67 
    68 
    68 /*
    69 /*
    69   constants and structures
    70   constants and structures
    70 */
    71 */
    71 
    72 
    72 static const int fixed_scale = 1 << 16;
    73 enum {
    73 static const int half_point = 1 << 15;
    74     fixed_scale = 1 << 16,
       
    75     half_point = 1 << 15
       
    76 };
    74 static const int buffer_size = 2048;
    77 static const int buffer_size = 2048;
    75 
    78 
    76 struct LinearGradientValues
    79 struct LinearGradientValues
    77 {
    80 {
    78     qreal dx;
    81     qreal dx;
   172     return buffer;
   175     return buffer;
   173 }
   176 }
   174 
   177 
   175 # define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
   178 # define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
   176 
   179 
   177 static const DestFetchProc destFetchProc[QImage::NImageFormats] =
   180 static DestFetchProc destFetchProc[QImage::NImageFormats] =
   178 {
   181 {
   179     0, // Format_Invalid
   182     0, // Format_Invalid
   180     destFetchMono, // Format_Mono,
   183     destFetchMono, // Format_Mono,
   181     destFetchMonoLsb, // Format_MonoLSB
   184     destFetchMonoLsb, // Format_MonoLSB
   182     0, // Format_Indexed8
   185     0, // Format_Indexed8
   320         *dest++ = DST(*src++);
   323         *dest++ = DST(*src++);
   321 }
   324 }
   322 
   325 
   323 # define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
   326 # define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
   324 
   327 
   325 static const DestStoreProc destStoreProc[QImage::NImageFormats] =
   328 static DestStoreProc destStoreProc[QImage::NImageFormats] =
   326 {
   329 {
   327     0, // Format_Invalid
   330     0, // Format_Invalid
   328     destStoreMono, // Format_Mono,
   331     destStoreMono, // Format_Mono,
   329     destStoreMonoLsb, // Format_MonoLSB
   332     destStoreMonoLsb, // Format_MonoLSB
   330     0, // Format_Indexed8
   333     0, // Format_Indexed8
   669 #endif
   672 #endif
   670 
   673 
   671     int image_width = data->texture.width;
   674     int image_width = data->texture.width;
   672     int image_height = data->texture.height;
   675     int image_height = data->texture.height;
   673 
   676 
       
   677     int image_x1 = data->texture.x1;
       
   678     int image_y1 = data->texture.y1;
       
   679     int image_x2 = data->texture.x2;
       
   680     int image_y2 = data->texture.y2;
       
   681 
   674     const qreal cx = x + 0.5;
   682     const qreal cx = x + 0.5;
   675     const qreal cy = y + 0.5;
   683     const qreal cy = y + 0.5;
   676 
   684 
   677     const uint *end = buffer + length;
   685     const uint *end = buffer + length;
   678     uint *b = buffer;
   686     uint *b = buffer;
   688 
   696 
   689         fx -= half_point;
   697         fx -= half_point;
   690         fy -= half_point;
   698         fy -= half_point;
   691         while (b < end) {
   699         while (b < end) {
   692             int x1 = (fx >> 16);
   700             int x1 = (fx >> 16);
   693             int x2 = x1 + 1;
   701             int x2;
   694             int y1 = (fy >> 16);
   702             int y1 = (fy >> 16);
   695             int y2 = y1 + 1;
   703             int y2;
   696 
       
   697             int distx = ((fx - (x1 << 16)) >> 8);
       
   698             int disty = ((fy - (y1 << 16)) >> 8);
       
   699             int idistx = 256 - distx;
       
   700             int idisty = 256 - disty;
       
   701 
   704 
   702             if (blendType == BlendTransformedBilinearTiled) {
   705             if (blendType == BlendTransformedBilinearTiled) {
   703                 x1 %= image_width;
   706                 x1 %= image_width;
       
   707                 if (x1 < 0) x1 += image_width;
       
   708                 x2 = x1 + 1;
   704                 x2 %= image_width;
   709                 x2 %= image_width;
       
   710 
   705                 y1 %= image_height;
   711                 y1 %= image_height;
       
   712                 if (y1 < 0) y1 += image_height;
       
   713                 y2 = y1 + 1;
   706                 y2 %= image_height;
   714                 y2 %= image_height;
   707 
       
   708                 if (x1 < 0) x1 += image_width;
       
   709                 if (x2 < 0) x2 += image_width;
       
   710                 if (y1 < 0) y1 += image_height;
       
   711                 if (y2 < 0) y2 += image_height;
       
   712 
       
   713                 Q_ASSERT(x1 >= 0 && x1 < image_width);
       
   714                 Q_ASSERT(x2 >= 0 && x2 < image_width);
       
   715                 Q_ASSERT(y1 >= 0 && y1 < image_height);
       
   716                 Q_ASSERT(y2 >= 0 && y2 < image_height);
       
   717             } else {
   715             } else {
   718                 x1 = qBound(0, x1, image_width - 1);
   716                 if (x1 < image_x1) {
   719                 x2 = qBound(0, x2, image_width - 1);
   717                     x2 = x1 = image_x1;
   720                 y1 = qBound(0, y1, image_height - 1);
   718                 } else if (x1 >= image_x2 - 1) {
   721                 y2 = qBound(0, y2, image_height - 1);
   719                     x2 = x1 = image_x2 - 1;
       
   720                 } else {
       
   721                     x2 = x1 + 1;
       
   722                 }
       
   723                 if (y1 < image_y1) {
       
   724                     y2 = y1 = image_y1;
       
   725                 } else if (y1 >= image_y2 - 1) {
       
   726                     y2 = y1 = image_y2 - 1;
       
   727                 } else {
       
   728                     y2 = y1 + 1;
       
   729                 }
   722             }
   730             }
       
   731 
       
   732             Q_ASSERT(x1 >= 0 && x1 < image_width);
       
   733             Q_ASSERT(x2 >= 0 && x2 < image_width);
       
   734             Q_ASSERT(y1 >= 0 && y1 < image_height);
       
   735             Q_ASSERT(y2 >= 0 && y2 < image_height);
   723 
   736 
   724             const uchar *s1 = data->texture.scanLine(y1);
   737             const uchar *s1 = data->texture.scanLine(y1);
   725             const uchar *s2 = data->texture.scanLine(y2);
   738             const uchar *s2 = data->texture.scanLine(y2);
   726 
   739 
   727             uint tl = fetch(s1, x1, data->texture.colorTable);
   740             uint tl = fetch(s1, x1, data->texture.colorTable);
   728             uint tr = fetch(s1, x2, data->texture.colorTable);
   741             uint tr = fetch(s1, x2, data->texture.colorTable);
   729             uint bl = fetch(s2, x1, data->texture.colorTable);
   742             uint bl = fetch(s2, x1, data->texture.colorTable);
   730             uint br = fetch(s2, x2, data->texture.colorTable);
   743             uint br = fetch(s2, x2, data->texture.colorTable);
   731 
   744 
       
   745             int distx = (fx & 0x0000ffff) >> 8;
       
   746             int disty = (fy & 0x0000ffff) >> 8;
       
   747             int idistx = 256 - distx;
       
   748             int idisty = 256 - disty;
       
   749 
   732             uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
   750             uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
   733             uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
   751             uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
   734             *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
   752             *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
   735 
   753 
   736             fx += fdx;
   754             fx += fdx;
   750             const qreal iw = fw == 0 ? 1 : 1 / fw;
   768             const qreal iw = fw == 0 ? 1 : 1 / fw;
   751             const qreal px = fx * iw - 0.5;
   769             const qreal px = fx * iw - 0.5;
   752             const qreal py = fy * iw - 0.5;
   770             const qreal py = fy * iw - 0.5;
   753 
   771 
   754             int x1 = int(px) - (px < 0);
   772             int x1 = int(px) - (px < 0);
   755             int x2 = x1 + 1;
   773             int x2;
   756             int y1 = int(py) - (py < 0);
   774             int y1 = int(py) - (py < 0);
   757             int y2 = y1 + 1;
   775             int y2;
   758 
   776 
   759             int distx = int((px - x1) * 256);
   777             int distx = int((px - x1) * 256);
   760             int disty = int((py - y1) * 256);
   778             int disty = int((py - y1) * 256);
   761             int idistx = 256 - distx;
   779             int idistx = 256 - distx;
   762             int idisty = 256 - disty;
   780             int idisty = 256 - disty;
   763 
   781 
   764             if (blendType == BlendTransformedBilinearTiled) {
   782             if (blendType == BlendTransformedBilinearTiled) {
   765                 x1 %= image_width;
   783                 x1 %= image_width;
       
   784                 if (x1 < 0) x1 += image_width;
       
   785                 x2 = x1 + 1;
   766                 x2 %= image_width;
   786                 x2 %= image_width;
       
   787 
   767                 y1 %= image_height;
   788                 y1 %= image_height;
       
   789                 if (y1 < 0) y1 += image_height;
       
   790                 y2 = y1 + 1;
   768                 y2 %= image_height;
   791                 y2 %= image_height;
   769 
       
   770                 if (x1 < 0) x1 += image_width;
       
   771                 if (x2 < 0) x2 += image_width;
       
   772                 if (y1 < 0) y1 += image_height;
       
   773                 if (y2 < 0) y2 += image_height;
       
   774 
       
   775                 Q_ASSERT(x1 >= 0 && x1 < image_width);
       
   776                 Q_ASSERT(x2 >= 0 && x2 < image_width);
       
   777                 Q_ASSERT(y1 >= 0 && y1 < image_height);
       
   778                 Q_ASSERT(y2 >= 0 && y2 < image_height);
       
   779             } else {
   792             } else {
   780                 x1 = qBound(0, x1, image_width - 1);
   793                 if (x1 < 0) {
   781                 x2 = qBound(0, x2, image_width - 1);
   794                     x2 = x1 = 0;
   782                 y1 = qBound(0, y1, image_height - 1);
   795                 } else if (x1 >= image_width - 1) {
   783                 y2 = qBound(0, y2, image_height - 1);
   796                     x2 = x1 = image_width - 1;
       
   797                 } else {
       
   798                     x2 = x1 + 1;
       
   799                 }
       
   800                 if (y1 < 0) {
       
   801                     y2 = y1 = 0;
       
   802                 } else if (y1 >= image_height - 1) {
       
   803                     y2 = y1 = image_height - 1;
       
   804                 } else {
       
   805                     y2 = y1 + 1;
       
   806                 }
   784             }
   807             }
       
   808 
       
   809             Q_ASSERT(x1 >= 0 && x1 < image_width);
       
   810             Q_ASSERT(x2 >= 0 && x2 < image_width);
       
   811             Q_ASSERT(y1 >= 0 && y1 < image_height);
       
   812             Q_ASSERT(y2 >= 0 && y2 < image_height);
   785 
   813 
   786             const uchar *s1 = data->texture.scanLine(y1);
   814             const uchar *s1 = data->texture.scanLine(y1);
   787             const uchar *s2 = data->texture.scanLine(y2);
   815             const uchar *s2 = data->texture.scanLine(y2);
   788 
   816 
   789             uint tl = fetch(s1, x1, data->texture.colorTable);
   817             uint tl = fetch(s1, x1, data->texture.colorTable);
  2824         *dest = (*src & ~(*dest)) | 0xff000000;
  2852         *dest = (*src & ~(*dest)) | 0xff000000;
  2825         ++dest; ++src;
  2853         ++dest; ++src;
  2826     }
  2854     }
  2827 }
  2855 }
  2828 
  2856 
  2829 static const CompositionFunctionSolid functionForModeSolid_C[] = {
  2857 static CompositionFunctionSolid functionForModeSolid_C[] = {
  2830         comp_func_solid_SourceOver,
  2858         comp_func_solid_SourceOver,
  2831         comp_func_solid_DestinationOver,
  2859         comp_func_solid_DestinationOver,
  2832         comp_func_solid_Clear,
  2860         comp_func_solid_Clear,
  2833         comp_func_solid_Source,
  2861         comp_func_solid_Source,
  2834         comp_func_solid_Destination,
  2862         comp_func_solid_Destination,
  2862         rasterop_solid_SourceAndNotDestination
  2890         rasterop_solid_SourceAndNotDestination
  2863 };
  2891 };
  2864 
  2892 
  2865 static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
  2893 static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C;
  2866 
  2894 
  2867 static const CompositionFunction functionForMode_C[] = {
  2895 static CompositionFunction functionForMode_C[] = {
  2868         comp_func_SourceOver,
  2896         comp_func_SourceOver,
  2869         comp_func_DestinationOver,
  2897         comp_func_DestinationOver,
  2870         comp_func_Clear,
  2898         comp_func_Clear,
  2871         comp_func_Source,
  2899         comp_func_Source,
  2872         comp_func_Destination,
  2900         comp_func_Destination,
  3698 
  3726 
  3699 template <>
  3727 template <>
  3700 Q_STATIC_TEMPLATE_SPECIALIZATION
  3728 Q_STATIC_TEMPLATE_SPECIALIZATION
  3701 inline quint32 alpha_4(const qargb8555 *src)
  3729 inline quint32 alpha_4(const qargb8555 *src)
  3702 {
  3730 {
  3703     Q_ASSERT((long(src) & 0x3) == 0);
  3731     Q_ASSERT((quintptr(src) & 0x3) == 0);
  3704     const quint8 *src8 = reinterpret_cast<const quint8*>(src);
  3732     const quint8 *src8 = reinterpret_cast<const quint8*>(src);
  3705     return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9];
  3733     return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9];
  3706 }
  3734 }
  3707 
  3735 
  3708 template <>
  3736 template <>
  3881 }
  3909 }
  3882 
  3910 
  3883 template <class DST, class SRC>
  3911 template <class DST, class SRC>
  3884 inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha)
  3912 inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha)
  3885 {
  3913 {
  3886     Q_ASSERT((long(dest) & 0x3) == 0);
  3914     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  3887     Q_ASSERT((long(src) & 0x3) == 0);
  3915     Q_ASSERT((quintptr(src) & 0x3) == 0);
  3888 
  3916 
  3889     const quint16 a = eff_alpha_2(alpha, dest);
  3917     const quint16 a = eff_alpha_2(alpha, dest);
  3890     const quint16 ia = eff_ialpha_2(alpha, dest);
  3918     const quint16 ia = eff_ialpha_2(alpha, dest);
  3891 
  3919 
  3892     dest[0] = DST(src[0]).byte_mul(a >> 8) + dest[0].byte_mul(ia >> 8);
  3920     dest[0] = DST(src[0]).byte_mul(a >> 8) + dest[0].byte_mul(ia >> 8);
  3955 
  3983 
  3956 template <class DST, class SRC>
  3984 template <class DST, class SRC>
  3957 inline void interpolate_pixel_2(DST *dest, quint8 a,
  3985 inline void interpolate_pixel_2(DST *dest, quint8 a,
  3958                                 const SRC *src, quint8 b)
  3986                                 const SRC *src, quint8 b)
  3959 {
  3987 {
  3960     Q_ASSERT((long(dest) & 0x3) == 0);
  3988     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  3961     Q_ASSERT((long(src) & 0x3) == 0);
  3989     Q_ASSERT((quintptr(src) & 0x3) == 0);
  3962 
  3990 
  3963     Q_ASSERT(!SRC::hasAlpha());
  3991     Q_ASSERT(!SRC::hasAlpha());
  3964 
  3992 
  3965     dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
  3993     dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
  3966     dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
  3994     dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
  4004 }
  4032 }
  4005 
  4033 
  4006 template <class DST, class SRC>
  4034 template <class DST, class SRC>
  4007 inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha)
  4035 inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha)
  4008 {
  4036 {
  4009     Q_ASSERT((long(dest) & 0x3) == 0);
  4037     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4010     Q_ASSERT((long(src) & 0x3) == 0);
  4038     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4011 
  4039 
  4012     const quint32 a = eff_alpha_4(alpha, dest);
  4040     const quint32 a = eff_alpha_4(alpha, dest);
  4013     const quint32 ia = eff_ialpha_4(alpha, dest);
  4041     const quint32 ia = eff_ialpha_4(alpha, dest);
  4014     dest[0] = DST(src[0]).byte_mul(a >> 24)
  4042     dest[0] = DST(src[0]).byte_mul(a >> 24)
  4015               + dest[0].byte_mul(ia >> 24);
  4043               + dest[0].byte_mul(ia >> 24);
  4024 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
  4052 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
  4025 template <>
  4053 template <>
  4026 inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src,
  4054 inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src,
  4027                                 quint32 alpha)
  4055                                 quint32 alpha)
  4028 {
  4056 {
  4029     Q_ASSERT((long(dest) & 0x3) == 0);
  4057     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4030     Q_ASSERT((long(src) & 0x3) == 0);
  4058     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4031 
  4059 
  4032     const quint32 a = eff_alpha_4(alpha, dest);
  4060     const quint32 a = eff_alpha_4(alpha, dest);
  4033     const quint32 ia = eff_ialpha_4(alpha, dest);
  4061     const quint32 ia = eff_ialpha_4(alpha, dest);
  4034     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4062     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4035     quint32 *dest32 = reinterpret_cast<quint32*>(dest);
  4063     quint32 *dest32 = reinterpret_cast<quint32*>(dest);
  4120 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
  4148 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
  4121 template <>
  4149 template <>
  4122 inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src,
  4150 inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src,
  4123                                 quint32 alpha)
  4151                                 quint32 alpha)
  4124 {
  4152 {
  4125     Q_ASSERT((long(dest) & 0x3) == 0);
  4153     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4126     Q_ASSERT((long(src) & 0x3) == 0);
  4154     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4127 
  4155 
  4128 
  4156 
  4129     const quint32 a = eff_alpha_4(alpha, dest);
  4157     const quint32 a = eff_alpha_4(alpha, dest);
  4130     const quint32 ia = eff_ialpha_4(alpha, dest);
  4158     const quint32 ia = eff_ialpha_4(alpha, dest);
  4131     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4159     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4216 
  4244 
  4217 template <>
  4245 template <>
  4218 inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src,
  4246 inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src,
  4219                                 quint32 alpha)
  4247                                 quint32 alpha)
  4220 {
  4248 {
  4221     Q_ASSERT((long(dest) & 0x3) == 0);
  4249     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4222     Q_ASSERT((long(src) & 0x3) == 0);
  4250     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4223 
  4251 
  4224     const quint32 a = eff_alpha_4(alpha, dest);
  4252     const quint32 a = eff_alpha_4(alpha, dest);
  4225     const quint32 ia = eff_ialpha_4(alpha, dest);
  4253     const quint32 ia = eff_ialpha_4(alpha, dest);
  4226     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4254     const quint32 *src32 = reinterpret_cast<const quint32*>(src);
  4227     quint32 *dest32 = reinterpret_cast<quint32*>(dest);
  4255     quint32 *dest32 = reinterpret_cast<quint32*>(dest);
  4289 
  4317 
  4290 template <class DST, class SRC>
  4318 template <class DST, class SRC>
  4291 inline void interpolate_pixel_4(DST *dest, quint8 a,
  4319 inline void interpolate_pixel_4(DST *dest, quint8 a,
  4292                                 const SRC *src, quint8 b)
  4320                                 const SRC *src, quint8 b)
  4293 {
  4321 {
  4294     Q_ASSERT((long(dest) & 0x3) == 0);
  4322     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4295     Q_ASSERT((long(src) & 0x3) == 0);
  4323     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4296 
  4324 
  4297     dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
  4325     dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b);
  4298     dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
  4326     dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b);
  4299     dest[2] = dest[2].byte_mul(a) + DST(src[2]).byte_mul(b);
  4327     dest[2] = dest[2].byte_mul(a) + DST(src[2]).byte_mul(b);
  4300     dest[3] = dest[3].byte_mul(a) + DST(src[3]).byte_mul(b);
  4328     dest[3] = dest[3].byte_mul(a) + DST(src[3]).byte_mul(b);
  4301 }
  4329 }
  4302 
  4330 
  4303 template <class DST, class SRC>
  4331 template <class DST, class SRC>
  4304 inline void blend_sourceOver_4(DST *dest, const SRC *src)
  4332 inline void blend_sourceOver_4(DST *dest, const SRC *src)
  4305 {
  4333 {
  4306     Q_ASSERT((long(dest) & 0x3) == 0);
  4334     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4307     Q_ASSERT((long(src) & 0x3) == 0);
  4335     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4308 
  4336 
  4309     const quint32 a = alpha_4(src);
  4337     const quint32 a = alpha_4(src);
  4310     if (a == 0xffffffff) {
  4338     if (a == 0xffffffff) {
  4311         qt_memconvert(dest, src, 4);
  4339         qt_memconvert(dest, src, 4);
  4312     } else if (a > 0) {
  4340     } else if (a > 0) {
  4317 }
  4345 }
  4318 
  4346 
  4319 template <>
  4347 template <>
  4320 inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
  4348 inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src)
  4321 {
  4349 {
  4322     Q_ASSERT((long(dest) & 0x3) == 0);
  4350     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4323     Q_ASSERT((long(src) & 0x3) == 0);
  4351     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4324 
  4352 
  4325     const quint32 a = alpha_4(src);
  4353     const quint32 a = alpha_4(src);
  4326     if (a == 0xffffffff) {
  4354     if (a == 0xffffffff) {
  4327         qt_memconvert(dest, src, 4);
  4355         qt_memconvert(dest, src, 4);
  4328     } else if (a > 0) {
  4356     } else if (a > 0) {
  4331 }
  4359 }
  4332 
  4360 
  4333 template <>
  4361 template <>
  4334 inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
  4362 inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src)
  4335 {
  4363 {
  4336     Q_ASSERT((long(dest) & 0x3) == 0);
  4364     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4337     Q_ASSERT((long(src) & 0x3) == 0);
  4365     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4338 
  4366 
  4339     const quint32 a = alpha_4(src);
  4367     const quint32 a = alpha_4(src);
  4340     if (a == 0xffffffff) {
  4368     if (a == 0xffffffff) {
  4341         qt_memconvert(dest, src, 4);
  4369         qt_memconvert(dest, src, 4);
  4342     } else if (a > 0) {
  4370     } else if (a > 0) {
  4345 }
  4373 }
  4346 
  4374 
  4347 template <>
  4375 template <>
  4348 inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src)
  4376 inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src)
  4349 {
  4377 {
  4350     Q_ASSERT((long(dest) & 0x3) == 0);
  4378     Q_ASSERT((quintptr(dest) & 0x3) == 0);
  4351     Q_ASSERT((long(src) & 0x3) == 0);
  4379     Q_ASSERT((quintptr(src) & 0x3) == 0);
  4352 
  4380 
  4353     const quint32 a = alpha_4(src);
  4381     const quint32 a = alpha_4(src);
  4354     if (a == 0xffffffff) {
  4382     if (a == 0xffffffff) {
  4355         qt_memconvert(dest, src, 4);
  4383         qt_memconvert(dest, src, 4);
  4356     } else if (a > 0) {
  4384     } else if (a > 0) {
  4408 void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
  4436 void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src,
  4409                                            quint8 coverage, int length)
  4437                                            quint8 coverage, int length)
  4410 {
  4438 {
  4411     Q_ASSERT(sizeof(DST) == 2);
  4439     Q_ASSERT(sizeof(DST) == 2);
  4412     Q_ASSERT(sizeof(SRC) == 2);
  4440     Q_ASSERT(sizeof(SRC) == 2);
  4413     Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
  4441     Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
  4414     Q_ASSERT(coverage > 0);
  4442     Q_ASSERT(coverage > 0);
  4415 
  4443 
  4416     const int align = quintptr(dest) & 0x3;
  4444     const int align = quintptr(dest) & 0x3;
  4417 
  4445 
  4418     if (coverage < 255) {
  4446     if (coverage < 255) {
  4476             ++src;
  4504             ++src;
  4477             --length;
  4505             --length;
  4478         }
  4506         }
  4479 
  4507 
  4480         while (length >= 2) {
  4508         while (length >= 2) {
  4481             Q_ASSERT((long(dest) & 3) == 0);
  4509             Q_ASSERT((quintptr(dest) & 3) == 0);
  4482             Q_ASSERT((long(src) & 3) == 0);
  4510             Q_ASSERT((quintptr(src) & 3) == 0);
  4483 
  4511 
  4484             const quint16 a = alpha_2(src);
  4512             const quint16 a = alpha_2(src);
  4485             if (a == 0xffff) {
  4513             if (a == 0xffff) {
  4486                 qt_memconvert(dest, src, 2);
  4514                 qt_memconvert(dest, src, 2);
  4487             } else if (a > 0) {
  4515             } else if (a > 0) {
  4508 
  4536 
  4509 template <class DST, class SRC>
  4537 template <class DST, class SRC>
  4510 void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src,
  4538 void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src,
  4511                                            quint8 coverage, int length)
  4539                                            quint8 coverage, int length)
  4512 {
  4540 {
  4513     Q_ASSERT((long(dest) & 0x3) == (long(src) & 0x3));
  4541     Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3));
  4514     Q_ASSERT(sizeof(DST) == 3);
  4542     Q_ASSERT(sizeof(DST) == 3);
  4515     Q_ASSERT(coverage > 0);
  4543     Q_ASSERT(coverage > 0);
  4516 
  4544 
  4517     const int align = quintptr(dest) & 0x3;
  4545     const int align = quintptr(dest) & 0x3;
  4518 
  4546 
  4731 }
  4759 }
  4732 
  4760 
  4733 static void blend_untransformed_rgb565(int count, const QSpan *spans,
  4761 static void blend_untransformed_rgb565(int count, const QSpan *spans,
  4734                                        void *userData)
  4762                                        void *userData)
  4735 {
  4763 {
  4736 #if defined(QT_QWS_DEPTH_16)
  4764 #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
  4737     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  4765     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  4738 
  4766 
  4739     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  4767     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  4740         blendUntransformed<qrgb565, qargb8565>(count, spans, userData);
  4768         blendUntransformed<qrgb565, qargb8565>(count, spans, userData);
  4741     else if (data->texture.format == QImage::Format_RGB16)
  4769     else if (data->texture.format == QImage::Format_RGB16)
  5069         blend_tiled_generic<RegularSpans>(count, spans, userData);
  5097         blend_tiled_generic<RegularSpans>(count, spans, userData);
  5070 }
  5098 }
  5071 
  5099 
  5072 static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
  5100 static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
  5073 {
  5101 {
  5074 #if defined(QT_QWS_DEPTH_16)
  5102 #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
  5075     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5103     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5076 
  5104 
  5077     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  5105     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  5078         blendTiled<qrgb565, qargb8565>(count, spans, userData);
  5106         blendTiled<qrgb565, qargb8565>(count, spans, userData);
  5079     else if (data->texture.format == QImage::Format_RGB16)
  5107     else if (data->texture.format == QImage::Format_RGB16)
  5138 #endif
  5166 #endif
  5139         blend_tiled_generic<RegularSpans>(count, spans, userData);
  5167         blend_tiled_generic<RegularSpans>(count, spans, userData);
  5140 }
  5168 }
  5141 
  5169 
  5142 
  5170 
  5143 template <SpanMethod spanMethod>
  5171 template <SpanMethod spanMethod, TextureBlendType blendType>  /* blendType must be either BlendTransformedBilinear or BlendTransformedBilinearTiled */
  5144 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
  5172 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
  5145 {
  5173 {
  5146     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5174     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5147     if (data->texture.format != QImage::Format_ARGB32_Premultiplied
  5175     if (data->texture.format != QImage::Format_ARGB32_Premultiplied
  5148         && data->texture.format != QImage::Format_RGB32) {
  5176         && data->texture.format != QImage::Format_RGB32) {
  5151     }
  5179     }
  5152 
  5180 
  5153     CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
  5181     CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
  5154     uint buffer[buffer_size];
  5182     uint buffer[buffer_size];
  5155 
  5183 
  5156     int image_x1 = data->texture.x1;
  5184     const int image_x1 = data->texture.x1;
  5157     int image_y1 = data->texture.y1;
  5185     const int image_y1 = data->texture.y1;
  5158     int image_x2 = data->texture.x2;
  5186     const int image_x2 = data->texture.x2;
  5159     int image_y2 = data->texture.y2;
  5187     const int image_y2 = data->texture.y2;
       
  5188     const int image_width = data->texture.width;
       
  5189     const int image_height = data->texture.height;
  5160     const int scanline_offset = data->texture.bytesPerLine / 4;
  5190     const int scanline_offset = data->texture.bytesPerLine / 4;
  5161 
  5191 
  5162     if (data->fast_matrix) {
  5192     if (data->fast_matrix) {
  5163         // The increment pr x in the scanline
  5193         // The increment pr x in the scanline
  5164         int fdx = (int)(data->m11 * fixed_scale);
  5194         int fdx = (int)(data->m11 * fixed_scale);
  5184                 int l = qMin(length, buffer_size);
  5214                 int l = qMin(length, buffer_size);
  5185                 const uint *end = buffer + l;
  5215                 const uint *end = buffer + l;
  5186                 uint *b = buffer;
  5216                 uint *b = buffer;
  5187                 while (b < end) {
  5217                 while (b < end) {
  5188                     int x1 = (x >> 16);
  5218                     int x1 = (x >> 16);
  5189                     int x2 = x1 + 1;
  5219                     int x2;
  5190                     int y1 = (y >> 16);
  5220                     int y1 = (y >> 16);
  5191                     int y2 = y1 + 1;
  5221                     int y2;
  5192 
  5222 
  5193                     int distx = ((x - (x1 << 16)) >> 8);
  5223                     if (blendType == BlendTransformedBilinearTiled) {
  5194                     int disty = ((y - (y1 << 16)) >> 8);
  5224                         x1 %= image_width;
  5195                     int idistx = 256 - distx;
  5225                         if (x1 < 0) x1 += image_width;
  5196                     int idisty = 256 - disty;
  5226                         x2 = x1 + 1;
  5197 
  5227                         x2 %= image_width;
  5198                     x1 = qBound(image_x1, x1, image_x2 - 1);
  5228 
  5199                     x2 = qBound(image_x1, x2, image_x2 - 1);
  5229                         y1 %= image_height;
  5200                     y1 = qBound(image_y1, y1, image_y2 - 1);
  5230                         if (y1 < 0) y1 += image_height;
  5201                     y2 = qBound(image_y1, y2, image_y2 - 1);
  5231                         y2 = y1 + 1;
       
  5232                         y2 %= image_height;
       
  5233 
       
  5234                         Q_ASSERT(x1 >= 0 && x1 < image_width);
       
  5235                         Q_ASSERT(x2 >= 0 && x2 < image_width);
       
  5236                         Q_ASSERT(y1 >= 0 && y1 < image_height);
       
  5237                         Q_ASSERT(y2 >= 0 && y2 < image_height);
       
  5238                     } else {
       
  5239                         if (x1 < image_x1) {
       
  5240                             x2 = x1 = image_x1;
       
  5241                         } else if (x1 >= image_x2 - 1) {
       
  5242                             x2 = x1 = image_x2 - 1;
       
  5243                         } else {
       
  5244                             x2 = x1 + 1;
       
  5245                         }
       
  5246                         if (y1 < image_y1) {
       
  5247                             y2 = y1 = image_y1;
       
  5248                         } else if (y1 >= image_y2 - 1) {
       
  5249                             y2 = y1 = image_y2 - 1;
       
  5250                         } else {
       
  5251                             y2 = y1 + 1;
       
  5252                         }
       
  5253                     }
  5202 
  5254 
  5203                     int y1_offset = y1 * scanline_offset;
  5255                     int y1_offset = y1 * scanline_offset;
  5204                     int y2_offset = y2 * scanline_offset;
  5256                     int y2_offset = y2 * scanline_offset;
  5205 
  5257 
  5206 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
  5258 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
  5212                     uint tl = image_bits[y1_offset + x1];
  5264                     uint tl = image_bits[y1_offset + x1];
  5213                     uint tr = image_bits[y1_offset + x2];
  5265                     uint tr = image_bits[y1_offset + x2];
  5214                     uint bl = image_bits[y2_offset + x1];
  5266                     uint bl = image_bits[y2_offset + x1];
  5215                     uint br = image_bits[y2_offset + x2];
  5267                     uint br = image_bits[y2_offset + x2];
  5216 #endif
  5268 #endif
       
  5269 
       
  5270                     int distx = (x & 0x0000ffff) >> 8;
       
  5271                     int disty = (y & 0x0000ffff) >> 8;
       
  5272                     int idistx = 256 - distx;
       
  5273                     int idisty = 256 - disty;
  5217 
  5274 
  5218                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
  5275                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
  5219                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
  5276                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
  5220                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
  5277                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
  5221                     ++b;
  5278                     ++b;
  5262                     const qreal iw = w == 0 ? 1 : 1 / w;
  5319                     const qreal iw = w == 0 ? 1 : 1 / w;
  5263                     const qreal px = x * iw - 0.5;
  5320                     const qreal px = x * iw - 0.5;
  5264                     const qreal py = y * iw - 0.5;
  5321                     const qreal py = y * iw - 0.5;
  5265 
  5322 
  5266                     int x1 = int(px) - (px < 0);
  5323                     int x1 = int(px) - (px < 0);
  5267                     int x2 = x1 + 1;
  5324                     int x2;
  5268                     int y1 = int(py) - (py < 0);
  5325                     int y1 = int(py) - (py < 0);
  5269                     int y2 = y1 + 1;
  5326                     int y2;
  5270 
  5327 
  5271                     int distx = int((px - x1) * 256);
  5328                     int distx = int((px - x1) * 256);
  5272                     int disty = int((py - y1) * 256);
  5329                     int disty = int((py - y1) * 256);
  5273                     int idistx = 256 - distx;
  5330                     int idistx = 256 - distx;
  5274                     int idisty = 256 - disty;
  5331                     int idisty = 256 - disty;
  5275 
  5332 
  5276                     x1 = qBound(image_x1, x1, image_x2 - 1);
  5333                     if (blendType == BlendTransformedBilinearTiled) {
  5277                     x2 = qBound(image_x1, x2, image_x2 - 1);
  5334                         x1 %= image_width;
  5278                     y1 = qBound(image_y1, y1, image_y2 - 1);
  5335                         if (x1 < 0) x1 += image_width;
  5279                     y2 = qBound(image_y1, y2, image_y2 - 1);
  5336                         x2 = x1 + 1;
       
  5337                         x2 %= image_width;
       
  5338 
       
  5339                         y1 %= image_height;
       
  5340                         if (y1 < 0) y1 += image_height;
       
  5341                         y2 = y1 + 1;
       
  5342                         y2 %= image_height;
       
  5343 
       
  5344                         Q_ASSERT(x1 >= 0 && x1 < image_width);
       
  5345                         Q_ASSERT(x2 >= 0 && x2 < image_width);
       
  5346                         Q_ASSERT(y1 >= 0 && y1 < image_height);
       
  5347                         Q_ASSERT(y2 >= 0 && y2 < image_height);
       
  5348                     } else {
       
  5349                         if (x1 < image_x1) {
       
  5350                             x2 = x1 = image_x1;
       
  5351                         } else if (x1 >= image_x2 - 1) {
       
  5352                             x2 = x1 = image_x2 - 1;
       
  5353                         } else {
       
  5354                             x2 = x1 + 1;
       
  5355                         }
       
  5356                         if (y1 < image_y1) {
       
  5357                             y2 = y1 = image_y1;
       
  5358                         } else if (y1 >= image_y2 - 1) {
       
  5359                             y2 = y1 = image_y2 - 1;
       
  5360                         } else {
       
  5361                             y2 = y1 + 1;
       
  5362                         }
       
  5363                     }
  5280 
  5364 
  5281                     int y1_offset = y1 * scanline_offset;
  5365                     int y1_offset = y1 * scanline_offset;
  5282                     int y2_offset = y2 * scanline_offset;
  5366                     int y2_offset = y2 * scanline_offset;
  5283 
  5367 
  5284 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
  5368 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
  5363 
  5447 
  5364                 const SRC *end = buffer + l;
  5448                 const SRC *end = buffer + l;
  5365                 SRC *b = buffer;
  5449                 SRC *b = buffer;
  5366                 while (b < end) {
  5450                 while (b < end) {
  5367                     int x1 = (x >> 16);
  5451                     int x1 = (x >> 16);
  5368                     int x2 = x1 + 1;
  5452                     int x2;
  5369                     int y1 = (y >> 16);
  5453                     int y1 = (y >> 16);
  5370                     int y2 = y1 + 1;
  5454                     int y2;
  5371 
  5455 
  5372                     const int distx = ((x - (x1 << 16)) >> 8);
  5456                     const int distx = (x & 0x0000ffff) >> 8;
  5373                     const int disty = ((y - (y1 << 16)) >> 8);
  5457                     const int disty = (y & 0x0000ffff) >> 8;
  5374                     x1 = qBound(src_minx, x1, src_maxx);
  5458 
  5375                     x2 = qBound(src_minx, x2, src_maxx);
  5459                     if (x1 < src_minx) {
  5376                     y1 = qBound(src_miny, y1, src_maxy);
  5460                         x2 = x1 = src_minx;
  5377                     y2 = qBound(src_miny, y2, src_maxy);
  5461                     } else if (x1 >= src_maxx) {
  5378 
  5462                         x2 = x1 = src_maxx;
       
  5463                     } else {
       
  5464                         x2 = x1 + 1;
       
  5465                     }
       
  5466                     if (y1 < src_miny) {
       
  5467                         y2 = y1 = src_miny;
       
  5468                     } else if (y1 >= src_maxy) {
       
  5469                         y2 = y1 = src_maxy;
       
  5470                     } else {
       
  5471                         y2 = y1 + 1;
       
  5472                     }
  5379 #if 0
  5473 #if 0
  5380                     if (x1 == x2) {
  5474                     if (x1 == x2) {
  5381                         if (y1 == y2) {
  5475                         if (y1 == y2) {
  5382                             *b = ((SRC*)data->texture.scanLine(y1))[x1];
  5476                             *b = ((SRC*)data->texture.scanLine(y1))[x1];
  5383                         } else {
  5477                         } else {
  5464                     const qreal iw = w == 0 ? 1 : 1 / w;
  5558                     const qreal iw = w == 0 ? 1 : 1 / w;
  5465                     const qreal px = x * iw - qreal(0.5);
  5559                     const qreal px = x * iw - qreal(0.5);
  5466                     const qreal py = y * iw - qreal(0.5);
  5560                     const qreal py = y * iw - qreal(0.5);
  5467 
  5561 
  5468                     int x1 = int(px) - (px < 0);
  5562                     int x1 = int(px) - (px < 0);
  5469                     int x2 = x1 + 1;
  5563                     int x2;
  5470                     int y1 = int(py) - (py < 0);
  5564                     int y1 = int(py) - (py < 0);
  5471                     int y2 = y1 + 1;
  5565                     int y2;
  5472 
  5566 
  5473                     const int distx = int((px - x1) * 256);
  5567                     const int distx = int((px - x1) * 256);
  5474                     const int disty = int((py - y1) * 256);
  5568                     const int disty = int((py - y1) * 256);
  5475 
  5569 
  5476                     x1 = qBound(src_minx, x1, src_maxx);
  5570                     if (x1 < src_minx) {
  5477                     x2 = qBound(src_minx, x2, src_maxx);
  5571                         x2 = x1 = src_minx;
  5478                     y1 = qBound(src_miny, y1, src_maxy);
  5572                     } else if (x1 >= src_maxx) {
  5479                     y2 = qBound(src_miny, y2, src_maxy);
  5573                         x2 = x1 = src_maxx;
       
  5574                     } else {
       
  5575                         x2 = x1 + 1;
       
  5576                     }
       
  5577                     if (y1 < src_miny) {
       
  5578                         y2 = y1 = src_miny;
       
  5579                     } else if (y1 >= src_maxy) {
       
  5580                         y2 = y1 = src_maxy;
       
  5581                     } else {
       
  5582                         y2 = y1 + 1;
       
  5583                     }
  5480 
  5584 
  5481                     const SRC *src1 = (SRC*)data->texture.scanLine(y1);
  5585                     const SRC *src1 = (SRC*)data->texture.scanLine(y1);
  5482                     const SRC *src2 = (SRC*)data->texture.scanLine(y2);
  5586                     const SRC *src2 = (SRC*)data->texture.scanLine(y2);
  5483                     SRC tl = src1[x1];
  5587                     SRC tl = src1[x1];
  5484                     const SRC tr = src1[x2];
  5588                     const SRC tr = src1[x2];
  5574 }
  5678 }
  5575 
  5679 
  5576 static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
  5680 static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
  5577                                               void *userData)
  5681                                               void *userData)
  5578 {
  5682 {
  5579 #if defined(QT_QWS_DEPTH_16)
  5683 #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
  5580     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5684     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  5581 
  5685 
  5582     if (data->texture.format == QImage::Format_RGB16)
  5686     if (data->texture.format == QImage::Format_RGB16)
  5583         blendTransformedBilinear<qrgb565, qrgb565>(count, spans, userData);
  5687         blendTransformedBilinear<qrgb565, qrgb565>(count, spans, userData);
  5584     else if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  5688     else if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  5640     else if (data->texture.format == QImage::Format_RGB444)
  5744     else if (data->texture.format == QImage::Format_RGB444)
  5641         blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData);
  5745         blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData);
  5642     else
  5746     else
  5643 #endif
  5747 #endif
  5644         blend_src_generic<RegularSpans>(count, spans, userData);
  5748         blend_src_generic<RegularSpans>(count, spans, userData);
  5645 }
       
  5646 
       
  5647 template <SpanMethod spanMethod>
       
  5648 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData)
       
  5649 {
       
  5650     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
       
  5651     if (data->texture.format != QImage::Format_ARGB32_Premultiplied
       
  5652         && data->texture.format != QImage::Format_RGB32) {
       
  5653         blend_src_generic<spanMethod>(count, spans, userData);
       
  5654         return;
       
  5655     }
       
  5656 
       
  5657     CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode];
       
  5658     uint buffer[buffer_size];
       
  5659 
       
  5660     int image_width = data->texture.width;
       
  5661     int image_height = data->texture.height;
       
  5662     const int scanline_offset = data->texture.bytesPerLine / 4;
       
  5663 
       
  5664     if (data->fast_matrix) {
       
  5665         // The increment pr x in the scanline
       
  5666         int fdx = (int)(data->m11 * fixed_scale);
       
  5667         int fdy = (int)(data->m12 * fixed_scale);
       
  5668 
       
  5669         while (count--) {
       
  5670             void *t = data->rasterBuffer->scanLine(spans->y);
       
  5671 
       
  5672             uint *target = ((uint *)t) + spans->x;
       
  5673             uint *image_bits = (uint *)data->texture.imageData;
       
  5674 
       
  5675             const qreal cx = spans->x + 0.5;
       
  5676             const qreal cy = spans->y + 0.5;
       
  5677 
       
  5678             int x = int((data->m21 * cy
       
  5679                          + data->m11 * cx + data->dx) * fixed_scale) - half_point;
       
  5680             int y = int((data->m22 * cy
       
  5681                          + data->m12 * cx + data->dy) * fixed_scale) - half_point;
       
  5682 
       
  5683             int length = spans->len;
       
  5684             const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
       
  5685             while (length) {
       
  5686                 int l = qMin(length, buffer_size);
       
  5687                 const uint *end = buffer + l;
       
  5688                 uint *b = buffer;
       
  5689                 while (b < end) {
       
  5690                     int x1 = (x >> 16);
       
  5691                     int x2 = (x1 + 1);
       
  5692                     int y1 = (y >> 16);
       
  5693                     int y2 = (y1 + 1);
       
  5694 
       
  5695                     int distx = ((x - (x1 << 16)) >> 8);
       
  5696                     int disty = ((y - (y1 << 16)) >> 8);
       
  5697                     int idistx = 256 - distx;
       
  5698                     int idisty = 256 - disty;
       
  5699 
       
  5700                     x1 %= image_width;
       
  5701                     x2 %= image_width;
       
  5702                     y1 %= image_height;
       
  5703                     y2 %= image_height;
       
  5704 
       
  5705                     if (x1 < 0) x1 += image_width;
       
  5706                     if (x2 < 0) x2 += image_width;
       
  5707                     if (y1 < 0) y1 += image_height;
       
  5708                     if (y2 < 0) y2 += image_height;
       
  5709 
       
  5710                     Q_ASSERT(x1 >= 0 && x1 < image_width);
       
  5711                     Q_ASSERT(x2 >= 0 && x2 < image_width);
       
  5712                     Q_ASSERT(y1 >= 0 && y1 < image_height);
       
  5713                     Q_ASSERT(y2 >= 0 && y2 < image_height);
       
  5714 
       
  5715                     int y1_offset = y1 * scanline_offset;
       
  5716                     int y2_offset = y2 * scanline_offset;
       
  5717 
       
  5718 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
       
  5719                     uint tl = gccBug(image_bits[y1_offset + x1]);
       
  5720                     uint tr = gccBug(image_bits[y1_offset + x2]);
       
  5721                     uint bl = gccBug(image_bits[y2_offset + x1]);
       
  5722                     uint br = gccBug(image_bits[y2_offset + x2]);
       
  5723 #else
       
  5724                     uint tl = image_bits[y1_offset + x1];
       
  5725                     uint tr = image_bits[y1_offset + x2];
       
  5726                     uint bl = image_bits[y2_offset + x1];
       
  5727                     uint br = image_bits[y2_offset + x2];
       
  5728 #endif
       
  5729 
       
  5730                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
       
  5731                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
       
  5732                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
       
  5733                     ++b;
       
  5734                     x += fdx;
       
  5735                     y += fdy;
       
  5736                 }
       
  5737                 if (spanMethod == RegularSpans)
       
  5738                     func(target, buffer, l, coverage);
       
  5739                 else
       
  5740                     drawBufferSpan(data, buffer, buffer_size,
       
  5741                                    spans->x + spans->len - length,
       
  5742                                    spans->y, l, coverage);
       
  5743                 target += l;
       
  5744                 length -= l;
       
  5745             }
       
  5746             ++spans;
       
  5747         }
       
  5748     } else {
       
  5749         const qreal fdx = data->m11;
       
  5750         const qreal fdy = data->m12;
       
  5751         const qreal fdw = data->m13;
       
  5752         while (count--) {
       
  5753             void *t = data->rasterBuffer->scanLine(spans->y);
       
  5754 
       
  5755             uint *target = ((uint *)t) + spans->x;
       
  5756             uint *image_bits = (uint *)data->texture.imageData;
       
  5757 
       
  5758             const qreal cx = spans->x + 0.5;
       
  5759             const qreal cy = spans->y + 0.5;
       
  5760 
       
  5761             qreal x = data->m21 * cy + data->m11 * cx + data->dx;
       
  5762             qreal y = data->m22 * cy + data->m12 * cx + data->dy;
       
  5763             qreal w = data->m23 * cy + data->m13 * cx + data->m33;
       
  5764 
       
  5765             int length = spans->len;
       
  5766             const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
       
  5767             while (length) {
       
  5768                 int l = qMin(length, buffer_size);
       
  5769                 const uint *end = buffer + l;
       
  5770                 uint *b = buffer;
       
  5771                 while (b < end) {
       
  5772                     const qreal iw = w == 0 ? 1 : 1 / w;
       
  5773                     const qreal px = x * iw - 0.5;
       
  5774                     const qreal py = y * iw - 0.5;
       
  5775 
       
  5776                     int x1 = int(px) - (px < 0);
       
  5777                     int x2 = x1 + 1;
       
  5778                     int y1 = int(py) - (py < 0);
       
  5779                     int y2 = y1 + 1;
       
  5780 
       
  5781                     int distx = int((px - x1) * 256);
       
  5782                     int disty = int((py - y1) * 256);
       
  5783                     int idistx = 256 - distx;
       
  5784                     int idisty = 256 - disty;
       
  5785 
       
  5786                     x1 %= image_width;
       
  5787                     x2 %= image_width;
       
  5788                     y1 %= image_height;
       
  5789                     y2 %= image_height;
       
  5790 
       
  5791                     if (x1 < 0) x1 += image_width;
       
  5792                     if (x2 < 0) x2 += image_width;
       
  5793                     if (y1 < 0) y1 += image_height;
       
  5794                     if (y2 < 0) y2 += image_height;
       
  5795 
       
  5796                     Q_ASSERT(x1 >= 0 && x1 < image_width);
       
  5797                     Q_ASSERT(x2 >= 0 && x2 < image_width);
       
  5798                     Q_ASSERT(y1 >= 0 && y1 < image_height);
       
  5799                     Q_ASSERT(y2 >= 0 && y2 < image_height);
       
  5800 
       
  5801                     int y1_offset = y1 * scanline_offset;
       
  5802                     int y2_offset = y2 * scanline_offset;
       
  5803 
       
  5804 #if defined(Q_IRIX_GCC3_3_WORKAROUND)
       
  5805                     uint tl = gccBug(image_bits[y1_offset + x1]);
       
  5806                     uint tr = gccBug(image_bits[y1_offset + x2]);
       
  5807                     uint bl = gccBug(image_bits[y2_offset + x1]);
       
  5808                     uint br = gccBug(image_bits[y2_offset + x2]);
       
  5809 #else
       
  5810                     uint tl = image_bits[y1_offset + x1];
       
  5811                     uint tr = image_bits[y1_offset + x2];
       
  5812                     uint bl = image_bits[y2_offset + x1];
       
  5813                     uint br = image_bits[y2_offset + x2];
       
  5814 #endif
       
  5815 
       
  5816                     uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
       
  5817                     uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
       
  5818                     *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
       
  5819                     ++b;
       
  5820                     x += fdx;
       
  5821                     y += fdy;
       
  5822                     w += fdw;
       
  5823                 }
       
  5824                 if (spanMethod == RegularSpans)
       
  5825                     func(target, buffer, l, coverage);
       
  5826                 else
       
  5827                     drawBufferSpan(data, buffer, buffer_size,
       
  5828                                    spans->x + spans->len - length,
       
  5829                                    spans->y, l, coverage);
       
  5830                 target += l;
       
  5831                 length -= l;
       
  5832             }
       
  5833             ++spans;
       
  5834         }
       
  5835     }
       
  5836 }
  5749 }
  5837 
  5750 
  5838 template <SpanMethod spanMethod>
  5751 template <SpanMethod spanMethod>
  5839 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData)
  5752 Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData)
  5840 {
  5753 {
  6161 }
  6074 }
  6162 
  6075 
  6163 static void blend_transformed_rgb565(int count, const QSpan *spans,
  6076 static void blend_transformed_rgb565(int count, const QSpan *spans,
  6164                                        void *userData)
  6077                                        void *userData)
  6165 {
  6078 {
  6166 #if defined(QT_QWS_DEPTH_16)
  6079 #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
  6167     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  6080     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  6168 
  6081 
  6169     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  6082     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  6170         blendTransformed<qrgb565, qargb8565>(count, spans, userData);
  6083         blendTransformed<qrgb565, qargb8565>(count, spans, userData);
  6171     else if (data->texture.format == QImage::Format_RGB16)
  6084     else if (data->texture.format == QImage::Format_RGB16)
  6574 }
  6487 }
  6575 
  6488 
  6576 static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
  6489 static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
  6577                                            void *userData)
  6490                                            void *userData)
  6578 {
  6491 {
  6579 #if defined(QT_QWS_DEPTH_16)
  6492 #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16)
  6580     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  6493     QSpanData *data = reinterpret_cast<QSpanData *>(userData);
  6581 
  6494 
  6582     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  6495     if (data->texture.format == QImage::Format_ARGB8565_Premultiplied)
  6583         blendTransformedTiled<qrgb565, qargb8565>(count, spans, userData);
  6496         blendTransformedTiled<qrgb565, qargb8565>(count, spans, userData);
  6584     else if (data->texture.format == QImage::Format_RGB16)
  6497     else if (data->texture.format == QImage::Format_RGB16)
  6735         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono
  6648         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono
  6736         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb
  6649         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb
  6737         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
  6650         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
  6738         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
  6651         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
  6739         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
  6652         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
  6740         SPANFUNC_POINTER(blend_transformed_bilinear_argb, RegularSpans), // ARGB32_Premultiplied
  6653         blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied
  6741         blend_transformed_bilinear_rgb565,
  6654         blend_transformed_bilinear_rgb565,
  6742         blend_transformed_bilinear_argb8565,
  6655         blend_transformed_bilinear_argb8565,
  6743         blend_transformed_bilinear_rgb666,
  6656         blend_transformed_bilinear_rgb666,
  6744         blend_transformed_bilinear_argb6666,
  6657         blend_transformed_bilinear_argb6666,
  6745         blend_transformed_bilinear_rgb555,
  6658         blend_transformed_bilinear_rgb555,
  6754         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono
  6667         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono
  6755         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb
  6668         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb
  6756         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
  6669         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8
  6757         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
  6670         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32
  6758         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
  6671         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32
  6759         SPANFUNC_POINTER(blend_transformed_bilinear_tiled_argb, RegularSpans), // ARGB32_Premultiplied
  6672         blend_transformed_bilinear_argb<RegularSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied
  6760         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16
  6673         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16
  6761         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied
  6674         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied
  6762         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666
  6675         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666
  6763         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB6666_Premultiplied
  6676         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB6666_Premultiplied
  6764         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB555
  6677         SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB555
  6853         blend_src_generic<CallbackSpans>,   // Mono
  6766         blend_src_generic<CallbackSpans>,   // Mono
  6854         blend_src_generic<CallbackSpans>,   // MonoLsb
  6767         blend_src_generic<CallbackSpans>,   // MonoLsb
  6855         blend_src_generic<CallbackSpans>,   // Indexed8
  6768         blend_src_generic<CallbackSpans>,   // Indexed8
  6856         blend_src_generic<CallbackSpans>,   // RGB32
  6769         blend_src_generic<CallbackSpans>,   // RGB32
  6857         blend_src_generic<CallbackSpans>,   // ARGB32
  6770         blend_src_generic<CallbackSpans>,   // ARGB32
  6858         blend_transformed_bilinear_argb<CallbackSpans>, // ARGB32_Premultiplied
  6771         blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinear>, // ARGB32_Premultiplied
  6859         blend_src_generic<CallbackSpans>,   // RGB16
  6772         blend_src_generic<CallbackSpans>,   // RGB16
  6860         blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
  6773         blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
  6861         blend_src_generic<CallbackSpans>,   // RGB666
  6774         blend_src_generic<CallbackSpans>,   // RGB666
  6862         blend_src_generic<CallbackSpans>,   // ARGB6666_Premultiplied
  6775         blend_src_generic<CallbackSpans>,   // ARGB6666_Premultiplied
  6863         blend_src_generic<CallbackSpans>,   // RGB555
  6776         blend_src_generic<CallbackSpans>,   // RGB555
  6872         blend_src_generic<CallbackSpans>,   // Mono
  6785         blend_src_generic<CallbackSpans>,   // Mono
  6873         blend_src_generic<CallbackSpans>,   // MonoLsb
  6786         blend_src_generic<CallbackSpans>,   // MonoLsb
  6874         blend_src_generic<CallbackSpans>,   // Indexed8
  6787         blend_src_generic<CallbackSpans>,   // Indexed8
  6875         blend_src_generic<CallbackSpans>,   // RGB32
  6788         blend_src_generic<CallbackSpans>,   // RGB32
  6876         blend_src_generic<CallbackSpans>,   // ARGB32
  6789         blend_src_generic<CallbackSpans>,   // ARGB32
  6877         blend_transformed_bilinear_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied
  6790         blend_transformed_bilinear_argb<CallbackSpans, BlendTransformedBilinearTiled>, // ARGB32_Premultiplied
  6878         blend_src_generic<CallbackSpans>,   // RGB16
  6791         blend_src_generic<CallbackSpans>,   // RGB16
  6879         blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
  6792         blend_src_generic<CallbackSpans>,   // ARGB8565_Premultiplied
  6880         blend_src_generic<CallbackSpans>,   // RGB666
  6793         blend_src_generic<CallbackSpans>,   // RGB666
  6881         blend_src_generic<CallbackSpans>,   // ARGB6666_Premultiplied
  6794         blend_src_generic<CallbackSpans>,   // ARGB6666_Premultiplied
  6882         blend_src_generic<CallbackSpans>,   // RGB555
  6795         blend_src_generic<CallbackSpans>,   // RGB555
  7132 
  7045 
  7133 #ifdef Q_WS_WIN
  7046 #ifdef Q_WS_WIN
  7134     int winSmooth;
  7047     int winSmooth;
  7135     if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
  7048     if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0))
  7136         smoothing = winSmooth / 1000.0;
  7049         smoothing = winSmooth / 1000.0;
       
  7050 
       
  7051     // Safeguard ourselves against corrupt registry values...
       
  7052     if (smoothing > 5 || smoothing < 1)
       
  7053         smoothing = 1.4;
       
  7054 
  7137 #endif
  7055 #endif
  7138 
  7056 
  7139 #ifdef Q_WS_X11
  7057 #ifdef Q_WS_X11
  7140     Q_UNUSED(smoothing);
  7058     Q_UNUSED(smoothing);
  7141     for (int i=0; i<256; ++i) {
  7059     for (int i=0; i<256; ++i) {
  7718 static void qt_memfill16_setup(quint16 *dest, quint16 value, int count);
  7636 static void qt_memfill16_setup(quint16 *dest, quint16 value, int count);
  7719 
  7637 
  7720 qt_memfill32_func qt_memfill32 = qt_memfill32_setup;
  7638 qt_memfill32_func qt_memfill32 = qt_memfill32_setup;
  7721 qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
  7639 qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
  7722 
  7640 
  7723 enum CPUFeatures {
       
  7724     None        = 0,
       
  7725     MMX         = 0x1,
       
  7726     MMXEXT      = 0x2,
       
  7727     MMX3DNOW    = 0x4,
       
  7728     MMX3DNOWEXT = 0x8,
       
  7729     SSE         = 0x10,
       
  7730     SSE2        = 0x20,
       
  7731     CMOV        = 0x40,
       
  7732     IWMMXT      = 0x80,
       
  7733     NEON        = 0x100
       
  7734 };
       
  7735 
       
  7736 static uint detectCPUFeatures()
       
  7737 {
       
  7738 #if defined (Q_OS_WINCE)
       
  7739 #if defined (ARM)
       
  7740     if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX))
       
  7741         return IWMMXT;
       
  7742 #elif defined(_X86_)
       
  7743     uint features = 0;
       
  7744 #if defined QT_HAVE_MMX
       
  7745     if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
       
  7746         features |= MMX;
       
  7747 #endif
       
  7748 #if defined QT_HAVE_3DNOW
       
  7749     if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
       
  7750         features |= MMX3DNOW;
       
  7751 #endif
       
  7752     return features;
       
  7753 #endif
       
  7754     return 0;
       
  7755 #elif defined(QT_HAVE_IWMMXT)
       
  7756     // runtime detection only available when running as a previlegied process
       
  7757     static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
       
  7758     return doIWMMXT ? IWMMXT : 0;
       
  7759 #elif defined(QT_HAVE_NEON)
       
  7760     static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
       
  7761     return doNEON ? NEON : 0;
       
  7762 #else
       
  7763     uint features = 0;
       
  7764 #if defined(__x86_64__) || defined(Q_OS_WIN64)
       
  7765     features = MMX|SSE|SSE2|CMOV;
       
  7766 #elif defined(__ia64__)
       
  7767     features = MMX|SSE|SSE2;
       
  7768 #elif defined(__i386__) || defined(_M_IX86)
       
  7769     unsigned int extended_result = 0;
       
  7770     uint result = 0;
       
  7771     /* see p. 118 of amd64 instruction set manual Vol3 */
       
  7772 #if defined(Q_CC_GNU)
       
  7773     asm ("push %%ebx\n"
       
  7774          "pushf\n"
       
  7775          "pop %%eax\n"
       
  7776          "mov %%eax, %%ebx\n"
       
  7777          "xor $0x00200000, %%eax\n"
       
  7778          "push %%eax\n"
       
  7779          "popf\n"
       
  7780          "pushf\n"
       
  7781          "pop %%eax\n"
       
  7782          "xor %%edx, %%edx\n"
       
  7783          "xor %%ebx, %%eax\n"
       
  7784          "jz 1f\n"
       
  7785 
       
  7786          "mov $0x00000001, %%eax\n"
       
  7787          "cpuid\n"
       
  7788          "1:\n"
       
  7789          "pop %%ebx\n"
       
  7790          "mov %%edx, %0\n"
       
  7791         : "=r" (result)
       
  7792         :
       
  7793         : "%eax", "%ecx", "%edx"
       
  7794         );
       
  7795 
       
  7796     asm ("push %%ebx\n"
       
  7797          "pushf\n"
       
  7798          "pop %%eax\n"
       
  7799          "mov %%eax, %%ebx\n"
       
  7800          "xor $0x00200000, %%eax\n"
       
  7801          "push %%eax\n"
       
  7802          "popf\n"
       
  7803          "pushf\n"
       
  7804          "pop %%eax\n"
       
  7805          "xor %%edx, %%edx\n"
       
  7806          "xor %%ebx, %%eax\n"
       
  7807          "jz 2f\n"
       
  7808 
       
  7809          "mov $0x80000000, %%eax\n"
       
  7810          "cpuid\n"
       
  7811          "cmp $0x80000000, %%eax\n"
       
  7812          "jbe 2f\n"
       
  7813          "mov $0x80000001, %%eax\n"
       
  7814          "cpuid\n"
       
  7815          "2:\n"
       
  7816          "pop %%ebx\n"
       
  7817          "mov %%edx, %0\n"
       
  7818         : "=r" (extended_result)
       
  7819         :
       
  7820         : "%eax", "%ecx", "%edx"
       
  7821         );
       
  7822 #elif defined (Q_OS_WIN)
       
  7823     _asm {
       
  7824         push eax
       
  7825         push ebx
       
  7826         push ecx
       
  7827         push edx
       
  7828         pushfd
       
  7829         pop eax
       
  7830         mov ebx, eax
       
  7831         xor eax, 00200000h
       
  7832         push eax
       
  7833         popfd
       
  7834         pushfd
       
  7835         pop eax
       
  7836         mov edx, 0
       
  7837         xor eax, ebx
       
  7838         jz skip
       
  7839 
       
  7840         mov eax, 1
       
  7841         cpuid
       
  7842         mov result, edx
       
  7843     skip:
       
  7844         pop edx
       
  7845         pop ecx
       
  7846         pop ebx
       
  7847         pop eax
       
  7848     }
       
  7849 
       
  7850     _asm {
       
  7851         push eax
       
  7852         push ebx
       
  7853         push ecx
       
  7854         push edx
       
  7855         pushfd
       
  7856         pop eax
       
  7857         mov ebx, eax
       
  7858         xor eax, 00200000h
       
  7859         push eax
       
  7860         popfd
       
  7861         pushfd
       
  7862         pop eax
       
  7863         mov edx, 0
       
  7864         xor eax, ebx
       
  7865         jz skip2
       
  7866 
       
  7867         mov eax, 80000000h
       
  7868         cpuid
       
  7869         cmp eax, 80000000h
       
  7870         jbe skip2
       
  7871         mov eax, 80000001h
       
  7872         cpuid
       
  7873         mov extended_result, edx
       
  7874     skip2:
       
  7875         pop edx
       
  7876         pop ecx
       
  7877         pop ebx
       
  7878         pop eax
       
  7879     }
       
  7880 #endif
       
  7881 
       
  7882     // result now contains the standard feature bits
       
  7883     if (result & (1u << 15))
       
  7884         features |= CMOV;
       
  7885     if (result & (1u << 23))
       
  7886         features |= MMX;
       
  7887     if (extended_result & (1u << 22))
       
  7888         features |= MMXEXT;
       
  7889     if (extended_result & (1u << 31))
       
  7890         features |= MMX3DNOW;
       
  7891     if (extended_result & (1u << 30))
       
  7892         features |= MMX3DNOWEXT;
       
  7893     if (result & (1u << 25))
       
  7894         features |= SSE;
       
  7895     if (result & (1u << 26))
       
  7896         features |= SSE2;
       
  7897 #endif // i386
       
  7898 
       
  7899     if (qgetenv("QT_NO_MMX").toInt())
       
  7900         features ^= MMX;
       
  7901     if (qgetenv("QT_NO_MMXEXT").toInt())
       
  7902         features ^= MMXEXT;
       
  7903     if (qgetenv("QT_NO_3DNOW").toInt())
       
  7904         features ^= MMX3DNOW;
       
  7905     if (qgetenv("QT_NO_3DNOWEXT").toInt())
       
  7906         features ^= MMX3DNOWEXT;
       
  7907     if (qgetenv("QT_NO_SSE").toInt())
       
  7908         features ^= SSE;
       
  7909     if (qgetenv("QT_NO_SSE2").toInt())
       
  7910         features ^= SSE2;
       
  7911 
       
  7912     return features;
       
  7913 #endif
       
  7914 }
       
  7915 
       
  7916 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
  7641 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
  7917 // Move these to qdrawhelper_arm.c when all
  7642 // Move these to qdrawhelper_arm.c when all
  7918 // functions are implemented using arm assembly.
  7643 // functions are implemented using arm assembly.
  7919 static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = {
  7644 static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = {
  7920         comp_func_solid_SourceOver,
  7645         comp_func_solid_SourceOver,
  8003 #endif // Q_CC_RVCT && QT_HAVE_ARMV6
  7728 #endif // Q_CC_RVCT && QT_HAVE_ARMV6
  8004 
  7729 
  8005 
  7730 
  8006 void qInitDrawhelperAsm()
  7731 void qInitDrawhelperAsm()
  8007 {
  7732 {
  8008     static uint features = 0xffffffff;
       
  8009     if (features != 0xffffffff)
       
  8010         return;
       
  8011     features = detectCPUFeatures();
       
  8012 
  7733 
  8013     qt_memfill32 = qt_memfill_template<quint32, quint32>;
  7734     qt_memfill32 = qt_memfill_template<quint32, quint32>;
  8014     qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>;
  7735     qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>;
  8015 
  7736 
  8016     CompositionFunction *functionForModeAsm = 0;
  7737     CompositionFunction *functionForModeAsm = 0;
  8017     CompositionFunctionSolid *functionForModeSolidAsm = 0;
  7738     CompositionFunctionSolid *functionForModeSolidAsm = 0;
  8018 
  7739 
  8019 #ifdef QT_NO_DEBUG
  7740     const uint features = qDetectCPUFeatures();
  8020     if (false) {
  7741     if (false) {
  8021 #ifdef QT_HAVE_SSE2
  7742 #ifdef QT_HAVE_SSE2
  8022     } else if (features & SSE2) {
  7743     } else if (features & SSE2) {
  8023         qt_memfill32 = qt_memfill32_sse2;
  7744         qt_memfill32 = qt_memfill32_sse2;
  8024         qt_memfill16 = qt_memfill16_sse2;
  7745         qt_memfill16 = qt_memfill16_sse2;
  8137         functionForModeSolidAsm = qt_functionForModeSolid_IWMMXT;
  7858         functionForModeSolidAsm = qt_functionForModeSolid_IWMMXT;
  8138         qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_iwmmxt;
  7859         qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_iwmmxt;
  8139     }
  7860     }
  8140 #endif // IWMMXT
  7861 #endif // IWMMXT
  8141 
  7862 
  8142 #endif // QT_NO_DEBUG
       
  8143 
       
  8144 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
  7863 #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
  8145         functionForModeAsm = qt_functionForMode_ARMv6;
  7864         functionForModeAsm = qt_functionForMode_ARMv6;
  8146         functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
  7865         functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
  8147 
  7866 
  8148         qt_memfill32 = qt_memfill32_armv6;
  7867         qt_memfill32 = qt_memfill32_armv6;
  8157         if (features & NEON) {
  7876         if (features & NEON) {
  8158             qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
  7877             qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
  8159             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
  7878             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
  8160             qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
  7879             qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
  8161             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
  7880             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
       
  7881             qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon;
       
  7882             qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon;
       
  7883 
       
  7884             qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon;
       
  7885             qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon;
       
  7886 
       
  7887             qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon;
       
  7888             qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon;
       
  7889 
       
  7890             qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon;
       
  7891 
       
  7892             functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon;
       
  7893             destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon;
       
  7894             destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon;
  8162         }
  7895         }
  8163 #endif
  7896 #endif
  8164 
  7897 
  8165     if (functionForModeSolidAsm) {
  7898     if (functionForModeSolidAsm) {
  8166         const int destinationMode = QPainter::CompositionMode_Destination;
  7899         const int destinationMode = QPainter::CompositionMode_Destination;