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); |
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) { |
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) |
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) |
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]; |
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 { |
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 |
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, |
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; |