src/gui/painting/qdrawhelper_neon.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
   577         for (int j = 0; j < tail; ++j)
   577         for (int j = 0; j < tail; ++j)
   578             data[i + j] = dstBuffer[j];
   578             data[i + j] = dstBuffer[j];
   579     }
   579     }
   580 }
   580 }
   581 
   581 
       
   582 void QT_FASTCALL comp_func_solid_SourceOver_neon(uint *destPixels, int length, uint color, uint const_alpha)
       
   583 {
       
   584     if ((const_alpha & qAlpha(color)) == 255) {
       
   585         QT_MEMFILL_UINT(destPixels, length, color);
       
   586     } else {
       
   587         if (const_alpha != 255)
       
   588             color = BYTE_MUL(color, const_alpha);
       
   589 
       
   590         const quint32 minusAlphaOfColor = qAlpha(~color);
       
   591         int x = 0;
       
   592 
       
   593         uint32_t *dst = (uint32_t *) destPixels;
       
   594         const uint32x4_t colorVector = vdupq_n_u32(color);
       
   595         uint16x8_t half = vdupq_n_u16(0x80);
       
   596         const uint16x8_t minusAlphaOfColorVector = vdupq_n_u16(minusAlphaOfColor);
       
   597 
       
   598         for (; x < length-3; x += 4) {
       
   599             uint32x4_t dstVector = vld1q_u32(&dst[x]);
       
   600 
       
   601             const uint8x16_t dst8 = vreinterpretq_u8_u32(dstVector);
       
   602 
       
   603             const uint8x8_t dst8_low = vget_low_u8(dst8);
       
   604             const uint8x8_t dst8_high = vget_high_u8(dst8);
       
   605 
       
   606             const uint16x8_t dst16_low = vmovl_u8(dst8_low);
       
   607             const uint16x8_t dst16_high = vmovl_u8(dst8_high);
       
   608 
       
   609             const uint16x8_t result16_low = qvbyte_mul_u16(dst16_low, minusAlphaOfColorVector, half);
       
   610             const uint16x8_t result16_high = qvbyte_mul_u16(dst16_high, minusAlphaOfColorVector, half);
       
   611 
       
   612             const uint32x2_t result32_low = vreinterpret_u32_u8(vmovn_u16(result16_low));
       
   613             const uint32x2_t result32_high = vreinterpret_u32_u8(vmovn_u16(result16_high));
       
   614 
       
   615             uint32x4_t blendedPixels = vcombine_u32(result32_low, result32_high);
       
   616             uint32x4_t colorPlusBlendedPixels = vaddq_u32(colorVector, blendedPixels);
       
   617             vst1q_u32(&dst[x], colorPlusBlendedPixels);
       
   618         }
       
   619 
       
   620         for (;x < length; ++x)
       
   621             destPixels[x] = color + BYTE_MUL(destPixels[x], minusAlphaOfColor);
       
   622     }
       
   623 }
       
   624 
       
   625 static const int tileSize = 32;
       
   626 
       
   627 extern "C" void qt_rotate90_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count);
       
   628 
       
   629 void qt_memrotate90_16_neon(const uchar *srcPixels, int w, int h, int sstride, uchar *destPixels, int dstride)
       
   630 {
       
   631     const ushort *src = (const ushort *)srcPixels;
       
   632     ushort *dest = (ushort *)destPixels;
       
   633 
       
   634     sstride /= sizeof(ushort);
       
   635     dstride /= sizeof(ushort);
       
   636 
       
   637     const int pack = sizeof(quint32) / sizeof(ushort);
       
   638     const int unaligned =
       
   639         qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h));
       
   640     const int restX = w % tileSize;
       
   641     const int restY = (h - unaligned) % tileSize;
       
   642     const int unoptimizedY = restY % pack;
       
   643     const int numTilesX = w / tileSize + (restX > 0);
       
   644     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
       
   645 
       
   646     for (int tx = 0; tx < numTilesX; ++tx) {
       
   647         const int startx = w - tx * tileSize - 1;
       
   648         const int stopx = qMax(startx - tileSize, 0);
       
   649 
       
   650         if (unaligned) {
       
   651             for (int x = startx; x >= stopx; --x) {
       
   652                 ushort *d = dest + (w - x - 1) * dstride;
       
   653                 for (int y = 0; y < unaligned; ++y) {
       
   654                     *d++ = src[y * sstride + x];
       
   655                 }
       
   656             }
       
   657         }
       
   658 
       
   659         for (int ty = 0; ty < numTilesY; ++ty) {
       
   660             const int starty = ty * tileSize + unaligned;
       
   661             const int stopy = qMin(starty + tileSize, h - unoptimizedY);
       
   662 
       
   663             int x = startx;
       
   664             // qt_rotate90_16_neon writes to eight rows, four pixels at a time
       
   665             for (; x >= stopx + 7; x -= 8) {
       
   666                 ushort *d = dest + (w - x - 1) * dstride + starty;
       
   667                 const ushort *s = &src[starty * sstride + x - 7];
       
   668                 qt_rotate90_16_neon(d, s, sstride * 2, dstride * 2, stopy - starty);
       
   669             }
       
   670 
       
   671             for (; x >= stopx; --x) {
       
   672                 quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty);
       
   673                 for (int y = starty; y < stopy; y += pack) {
       
   674                     quint32 c = src[y * sstride + x];
       
   675                     for (int i = 1; i < pack; ++i) {
       
   676                         const int shift = (sizeof(int) * 8 / pack * i);
       
   677                         const ushort color = src[(y + i) * sstride + x];
       
   678                         c |= color << shift;
       
   679                     }
       
   680                     *d++ = c;
       
   681                 }
       
   682             }
       
   683         }
       
   684 
       
   685         if (unoptimizedY) {
       
   686             const int starty = h - unoptimizedY;
       
   687             for (int x = startx; x >= stopx; --x) {
       
   688                 ushort *d = dest + (w - x - 1) * dstride + starty;
       
   689                 for (int y = starty; y < h; ++y) {
       
   690                     *d++ = src[y * sstride + x];
       
   691                 }
       
   692             }
       
   693         }
       
   694     }
       
   695 }
       
   696 
       
   697 extern "C" void qt_rotate270_16_neon(quint16 *dst, const quint16 *src, int sstride, int dstride, int count);
       
   698 
       
   699 void qt_memrotate270_16_neon(const uchar *srcPixels, int w, int h,
       
   700                              int sstride,
       
   701                              uchar *destPixels, int dstride)
       
   702 {
       
   703     const ushort *src = (const ushort *)srcPixels;
       
   704     ushort *dest = (ushort *)destPixels;
       
   705 
       
   706     sstride /= sizeof(ushort);
       
   707     dstride /= sizeof(ushort);
       
   708 
       
   709     const int pack = sizeof(quint32) / sizeof(ushort);
       
   710     const int unaligned =
       
   711         qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(ushort)), uint(h));
       
   712     const int restX = w % tileSize;
       
   713     const int restY = (h - unaligned) % tileSize;
       
   714     const int unoptimizedY = restY % pack;
       
   715     const int numTilesX = w / tileSize + (restX > 0);
       
   716     const int numTilesY = (h - unaligned) / tileSize + (restY >= pack);
       
   717 
       
   718     for (int tx = 0; tx < numTilesX; ++tx) {
       
   719         const int startx = tx * tileSize;
       
   720         const int stopx = qMin(startx + tileSize, w);
       
   721 
       
   722         if (unaligned) {
       
   723             for (int x = startx; x < stopx; ++x) {
       
   724                 ushort *d = dest + x * dstride;
       
   725                 for (int y = h - 1; y >= h - unaligned; --y) {
       
   726                     *d++ = src[y * sstride + x];
       
   727                 }
       
   728             }
       
   729         }
       
   730 
       
   731         for (int ty = 0; ty < numTilesY; ++ty) {
       
   732             const int starty = h - 1 - unaligned - ty * tileSize;
       
   733             const int stopy = qMax(starty - tileSize, unoptimizedY);
       
   734 
       
   735             int x = startx;
       
   736             // qt_rotate90_16_neon writes to eight rows, four pixels at a time
       
   737             for (; x < stopx - 7; x += 8) {
       
   738                 ushort *d = dest + x * dstride + h - 1 - starty;
       
   739                 const ushort *s = &src[starty * sstride + x];
       
   740                 qt_rotate90_16_neon(d + 7 * dstride, s, -sstride * 2, -dstride * 2, starty - stopy);
       
   741             }
       
   742 
       
   743             for (; x < stopx; ++x) {
       
   744                 quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride
       
   745                                                         + h - 1 - starty);
       
   746                 for (int y = starty; y > stopy; y -= pack) {
       
   747                     quint32 c = src[y * sstride + x];
       
   748                     for (int i = 1; i < pack; ++i) {
       
   749                         const int shift = (sizeof(int) * 8 / pack * i);
       
   750                         const ushort color = src[(y - i) * sstride + x];
       
   751                         c |= color << shift;
       
   752                     }
       
   753                     *d++ = c;
       
   754                 }
       
   755             }
       
   756         }
       
   757         if (unoptimizedY) {
       
   758             const int starty = unoptimizedY - 1;
       
   759             for (int x = startx; x < stopx; ++x) {
       
   760                 ushort *d = dest + x * dstride + h - 1 - starty;
       
   761                 for (int y = starty; y >= 0; --y) {
       
   762                     *d++ = src[y * sstride + x];
       
   763                 }
       
   764             }
       
   765         }
       
   766     }
       
   767 }
       
   768 
   582 QT_END_NAMESPACE
   769 QT_END_NAMESPACE
   583 
   770 
   584 #endif // QT_HAVE_NEON
   771 #endif // QT_HAVE_NEON
   585 
   772