Merge drawhelper convert-from and store
Avoids using an intermediate buffer on store and simplifies the code. Change-Id: I2dc4e735eb770f90dc99fe0f513b4df3b35ee793 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>bb10
parent
6a39e49a6c
commit
648ee7aa02
|
|
@ -2303,8 +2303,7 @@ QRgb QImage::pixel(int x, int y) const
|
|||
}
|
||||
const QPixelLayout *layout = &qPixelLayouts[d->format];
|
||||
uint result;
|
||||
const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1);
|
||||
return *layout->convertToARGB32PM(&result, ptr, 1, 0, 0);
|
||||
return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -2405,9 +2404,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
|
|||
}
|
||||
|
||||
const QPixelLayout *layout = &qPixelLayouts[d->format];
|
||||
uint result;
|
||||
const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, 0, 0);
|
||||
qStorePixels[layout->bpp](s, ptr, x, 1);
|
||||
layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -2584,14 +2581,13 @@ bool QImage::allGray() const
|
|||
|
||||
uint buffer[BufferSize];
|
||||
const QPixelLayout *layout = &qPixelLayouts[d->format];
|
||||
FetchPixelsFunc fetch = qFetchPixels[layout->bpp];
|
||||
const auto fetch = layout->fetchToARGB32PM;
|
||||
for (int j = 0; j < d->height; ++j) {
|
||||
const uchar *b = constScanLine(j);
|
||||
int x = 0;
|
||||
while (x < d->width) {
|
||||
int l = qMin(d->width - x, BufferSize);
|
||||
const uint *ptr = fetch(buffer, b, x, l);
|
||||
ptr = layout->convertToARGB32PM(buffer, ptr, l, 0, 0);
|
||||
const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr);
|
||||
for (int i = 0; i < l; ++i) {
|
||||
if (!qIsGray(ptr[i]))
|
||||
return false;
|
||||
|
|
@ -3209,9 +3205,7 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
|
|||
|
||||
inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout)
|
||||
{
|
||||
FetchPixelsFunc fetch = qFetchPixels[layout->bpp];
|
||||
StorePixelsFunc store = qStorePixels[layout->bpp];
|
||||
RbSwapFunc func = layout->rbSwap;
|
||||
const RbSwapFunc func = layout->rbSwap;
|
||||
if (!func) {
|
||||
qWarning("Trying to rb-swap an image format where it doesn't make sense");
|
||||
if (src != dst)
|
||||
|
|
@ -3219,19 +3213,10 @@ inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage
|
|||
return;
|
||||
}
|
||||
|
||||
uint buffer[BufferSize];
|
||||
for (int i = 0; i < height; ++i) {
|
||||
uchar *q = dst->scanLine(i);
|
||||
const uchar *p = src->constScanLine(i);
|
||||
int x = 0;
|
||||
while (x < width) {
|
||||
int l = qMin(width - x, BufferSize);
|
||||
const uint *ptr = fetch(buffer, p, x, l);
|
||||
ptr = func(buffer, ptr, l);
|
||||
if (q != (const uchar *)ptr)
|
||||
store(q, ptr, x, l);
|
||||
x += l;
|
||||
}
|
||||
func(q, p, width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,26 +118,35 @@ void qGamma_correct_back_to_linear_cs(QImage *image)
|
|||
Internal routines for converting image depth.
|
||||
*****************************************************************************/
|
||||
|
||||
// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion.
|
||||
static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion
|
||||
static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = 0xff000000 | qUnpremultiply(src[i]);
|
||||
return buffer;
|
||||
d[i] = 0xff000000 | qUnpremultiply(src[i]);
|
||||
}
|
||||
|
||||
static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
static void QT_FASTCALL storeRGB32FromARGB32(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = 0xff000000 |src[i];
|
||||
d[i] = 0xff000000 | src[i];
|
||||
}
|
||||
|
||||
static const uint *QT_FASTCALL fetchRGB32ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
const uint *s = reinterpret_cast<const uint *>(src) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = 0xff000000 | s[i];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
|
||||
extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
#endif
|
||||
|
||||
void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags)
|
||||
|
|
@ -152,34 +161,32 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
|||
const uchar *srcData = src->data;
|
||||
uchar *destData = dest->data;
|
||||
|
||||
const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
|
||||
const StorePixelsFunc store = qStorePixels[destLayout->bpp];
|
||||
ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
|
||||
ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->convertFromRGB32) {
|
||||
// If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
|
||||
convertFromARGB32PM = destLayout->convertFromRGB32;
|
||||
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method.
|
||||
store = destLayout->storeFromRGB32;
|
||||
} else {
|
||||
// The drawhelpers do not mask the alpha value in RGB32, we want to here.
|
||||
if (src->format == QImage::Format_RGB32)
|
||||
convertToARGB32PM = maskRGB32;
|
||||
fetch = fetchRGB32ToARGB32PM;
|
||||
if (dest->format == QImage::Format_RGB32) {
|
||||
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
|
||||
if (qCpuHasFeature(SSE4_1))
|
||||
convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
|
||||
store = storeRGB32FromARGB32PM_sse4;
|
||||
else
|
||||
#endif
|
||||
convertFromARGB32PM = convertRGB32FromARGB32PM;
|
||||
store = storeRGB32FromARGB32PM;
|
||||
}
|
||||
}
|
||||
if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) &&
|
||||
!destLayout->hasAlphaChannel && destLayout->convertFromRGB32) {
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM;
|
||||
fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
|
||||
if (dest->format == QImage::Format_RGB32)
|
||||
convertFromARGB32PM = maskRGB32;
|
||||
store = storeRGB32FromARGB32;
|
||||
else
|
||||
convertFromARGB32PM = destLayout->convertFromRGB32;
|
||||
store = destLayout->storeFromRGB32;
|
||||
}
|
||||
QDitherInfo dither;
|
||||
QDitherInfo *ditherPtr = 0;
|
||||
|
|
@ -196,11 +203,8 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
|||
buffer = reinterpret_cast<uint *>(destData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const uint *ptr = fetch(buffer, srcData, x, l);
|
||||
ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr);
|
||||
ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr);
|
||||
if (ptr != reinterpret_cast<uint *>(destData))
|
||||
store(destData, ptr, x, l);
|
||||
const uint *ptr = fetch(buffer, srcData, x, l, 0, ditherPtr);
|
||||
store(destData, ptr, x, l, 0, ditherPtr);
|
||||
x += l;
|
||||
}
|
||||
srcData += src->bytes_per_line;
|
||||
|
|
@ -216,38 +220,37 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
|||
if (data->depth != qt_depthForFormat(dst_format))
|
||||
return false;
|
||||
|
||||
uint buffer[BufferSize];
|
||||
uint buf[BufferSize];
|
||||
uint *buffer = buf;
|
||||
const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
|
||||
const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
|
||||
uchar *srcData = data->data;
|
||||
|
||||
const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp];
|
||||
const StorePixelsFunc store = qStorePixels[destLayout->bpp];
|
||||
ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM;
|
||||
ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->convertFromRGB32) {
|
||||
// If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
|
||||
convertFromARGB32PM = destLayout->convertFromRGB32;
|
||||
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
|
||||
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method.
|
||||
store = destLayout->storeFromRGB32;
|
||||
} else {
|
||||
if (data->format == QImage::Format_RGB32)
|
||||
convertToARGB32PM = maskRGB32;
|
||||
fetch = fetchRGB32ToARGB32PM;
|
||||
if (dst_format == QImage::Format_RGB32) {
|
||||
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
|
||||
if (qCpuHasFeature(SSE4_1))
|
||||
convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
|
||||
store = storeRGB32FromARGB32PM_sse4;
|
||||
else
|
||||
#endif
|
||||
convertFromARGB32PM = convertRGB32FromARGB32PM;
|
||||
store = storeRGB32FromARGB32PM;
|
||||
}
|
||||
}
|
||||
if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) &&
|
||||
!destLayout->hasAlphaChannel && destLayout->convertFromRGB32) {
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
convertToARGB32PM = qPixelLayouts[data->format + 1].convertToARGB32PM;
|
||||
if (dst_format == QImage::Format_RGB32)
|
||||
convertFromARGB32PM = maskRGB32;
|
||||
fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
|
||||
if (data->format == QImage::Format_RGB32)
|
||||
store = storeRGB32FromARGB32;
|
||||
else
|
||||
convertFromARGB32PM = destLayout->convertFromRGB32;
|
||||
store = destLayout->storeFromRGB32;
|
||||
}
|
||||
QDitherInfo dither;
|
||||
QDitherInfo *ditherPtr = 0;
|
||||
|
|
@ -259,13 +262,13 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
|||
int x = 0;
|
||||
while (x < data->width) {
|
||||
dither.x = x;
|
||||
int l = qMin(data->width - x, BufferSize);
|
||||
const uint *ptr = fetch(buffer, srcData, x, l);
|
||||
ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr);
|
||||
ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr);
|
||||
// The conversions might be passthrough and not use the buffer, in that case we are already done.
|
||||
if (srcData != (const uchar*)ptr)
|
||||
store(srcData, ptr, x, l);
|
||||
int l = data->width - x;
|
||||
if (destLayout->bpp == QPixelLayout::BPP32)
|
||||
buffer = reinterpret_cast<uint *>(srcData) + x;
|
||||
else
|
||||
l = qMin(l, BufferSize);
|
||||
const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr);
|
||||
store(srcData, ptr, x, l, nullptr, ditherPtr);
|
||||
x += l;
|
||||
}
|
||||
srcData += data->bytes_per_line;
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]);
|
||||
return buffer;
|
||||
d[i] = 0xff000000 | qUnpremultiply_sse4(src[i]);
|
||||
}
|
||||
|
||||
void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
|
||||
|
|
|
|||
|
|
@ -150,13 +150,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color)
|
|||
m_alpha = true;
|
||||
}
|
||||
|
||||
uint pixel = qPremultiply(color.rgba());
|
||||
const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()];
|
||||
Q_ASSERT(layout->convertFromARGB32PM);
|
||||
layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0);
|
||||
|
||||
//so premultiplied formats are supported and ARGB32 and RGB32
|
||||
blittable()->lock()->fill(pixel);
|
||||
blittable()->lock()->fill(color);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,17 +193,12 @@ void QRasterPlatformPixmap::fill(const QColor &color)
|
|||
if (alpha != 255) {
|
||||
if (!image.hasAlphaChannel()) {
|
||||
QImage::Format toFormat = qt_alphaVersionForPainting(image.format());
|
||||
if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) {
|
||||
image.detach();
|
||||
image.d->format = toFormat;
|
||||
} else {
|
||||
if (!image.reinterpretAsFormat(toFormat))
|
||||
image = QImage(image.width(), image.height(), toFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
pixel = qPremultiply(color.rgba());
|
||||
const QPixelLayout *layout = &qPixelLayouts[image.format()];
|
||||
layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0);
|
||||
image.fill(color);
|
||||
return;
|
||||
} else if (image.format() == QImage::Format_Alpha8) {
|
||||
pixel = qAlpha(color.rgba());
|
||||
} else if (image.format() == QImage::Format_Grayscale8) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1153,18 +1153,14 @@ static inline void convertARGBToARGB32PM_neon(uint *buffer, const uint *src, int
|
|||
}
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL convertARGB32ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *)
|
||||
{
|
||||
convertARGBToARGB32PM_neon<false>(buffer, src, count);
|
||||
return buffer;
|
||||
convertARGBToARGB32PM_neon<false>(buffer, buffer, count);
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL convertRGBA8888ToARGB32PM_neon(uint *buffer, int count, const QVector<QRgb> *)
|
||||
{
|
||||
convertARGBToARGB32PM_neon<true>(buffer, src, count);
|
||||
return buffer;
|
||||
convertARGBToARGB32PM_neon<true>(buffer, buffer, count);
|
||||
}
|
||||
|
||||
#endif // Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
|
|
|
|||
|
|
@ -1227,11 +1227,15 @@ struct QDitherInfo {
|
|||
int y;
|
||||
};
|
||||
|
||||
typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef const uint *(QT_FASTCALL *FetchAndConvertPixelsFunc)(uint *buffer, const uchar *src, int index, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef void (QT_FASTCALL *ConvertAndStorePixelsFunc)(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
|
||||
typedef void (QT_FASTCALL *ConvertFunc)(uint *buffer, int count, const QVector<QRgb> *clut);
|
||||
typedef const QRgba64 *(QT_FASTCALL *ConvertFunc64)(QRgba64 *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *clut, QDitherInfo *dither);
|
||||
typedef const uint *(QT_FASTCALL *RbSwapFunc)(uint *buffer, const uint *src, int count);
|
||||
typedef void (QT_FASTCALL *RbSwapFunc)(uchar *dst, const uchar *src, int count);
|
||||
|
||||
|
||||
struct QPixelLayout
|
||||
|
|
@ -1253,17 +1257,13 @@ struct QPixelLayout
|
|||
BPP bpp;
|
||||
RbSwapFunc rbSwap;
|
||||
ConvertFunc convertToARGB32PM;
|
||||
ConvertFunc convertFromARGB32PM;
|
||||
ConvertFunc convertFromRGB32;
|
||||
ConvertFunc64 convertToARGB64PM;
|
||||
FetchAndConvertPixelsFunc fetchToARGB32PM;
|
||||
ConvertAndStorePixelsFunc storeFromARGB32PM;
|
||||
ConvertAndStorePixelsFunc storeFromRGB32;
|
||||
};
|
||||
|
||||
typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count);
|
||||
typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count);
|
||||
|
||||
extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
|
||||
extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount];
|
||||
extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount];
|
||||
|
||||
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
|
||||
|
||||
|
|
|
|||
|
|
@ -93,59 +93,55 @@ static inline void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int
|
|||
}
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *)
|
||||
{
|
||||
convertARGBToARGB32PM_sse4<false>(buffer, src, count);
|
||||
return buffer;
|
||||
convertARGBToARGB32PM_sse4<false>(buffer, buffer, count);
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, int count, const QVector<QRgb> *)
|
||||
{
|
||||
convertARGBToARGB32PM_sse4<true>(buffer, src, count);
|
||||
return buffer;
|
||||
convertARGBToARGB32PM_sse4<true>(buffer, buffer, count);
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL storeARGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qUnpremultiply_sse4(src[i]);
|
||||
return buffer;
|
||||
d[i] = qUnpremultiply_sse4(src[i]);
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL storeRGBA8888FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i]));
|
||||
return buffer;
|
||||
d[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i]));
|
||||
}
|
||||
|
||||
const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL storeRGBXFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i]));
|
||||
return buffer;
|
||||
d[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i]));
|
||||
}
|
||||
|
||||
template<QtPixelOrder PixelOrder>
|
||||
const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *)
|
||||
{
|
||||
uint *d = reinterpret_cast<uint *>(dest) + index;
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
|
||||
return buffer;
|
||||
d[i] = qConvertArgb32ToA2rgb30_sse4<PixelOrder>(src[i]);
|
||||
}
|
||||
|
||||
template
|
||||
const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderBGR>(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
template
|
||||
const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uint *buffer, const uint *src, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4<PixelOrderRGB>(uchar *dest, const uint *src, int index, int count,
|
||||
const QVector<QRgb> *, QDitherInfo *);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
|
|
|||
|
|
@ -167,61 +167,12 @@ void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void store_uint24_ssse3(uchar *dst, const uint *src, int len)
|
||||
const uint *QT_FASTCALL fetchPixelsBPP24_ssse3(uint *buffer, const uchar *src, int index, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
quint24 *dst24 = reinterpret_cast<quint24*>(dst);
|
||||
// Align dst on 16 bytes
|
||||
for (; i < len && (reinterpret_cast<quintptr>(dst24) & 0xf); ++i)
|
||||
*dst24++ = quint24(*src++);
|
||||
|
||||
// Shuffle masks for first and second half of every output, all outputs are aligned so the shuffled ends are not used.
|
||||
const __m128i shuffleMask1 = _mm_setr_epi8(char(0x80), char(0x80), char(0x80), char(0x80), 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12);
|
||||
const __m128i shuffleMask2 = _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, char(0x80), char(0x80), char(0x80), char(0x80));
|
||||
|
||||
const __m128i *inVectorPtr = (const __m128i *)src;
|
||||
__m128i *dstVectorPtr = (__m128i *)dst24;
|
||||
|
||||
for (; i < (len - 15); i += 16) {
|
||||
// Load four vectors, store three.
|
||||
// Create each output vector by combining two shuffled input vectors.
|
||||
__m128i srcVector1 = _mm_loadu_si128(inVectorPtr);
|
||||
++inVectorPtr;
|
||||
__m128i srcVector2 = _mm_loadu_si128(inVectorPtr);
|
||||
++inVectorPtr;
|
||||
__m128i outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1);
|
||||
__m128i outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2);
|
||||
__m128i outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 4);
|
||||
_mm_store_si128(dstVectorPtr, outputVector);
|
||||
++dstVectorPtr;
|
||||
|
||||
srcVector1 = _mm_loadu_si128(inVectorPtr);
|
||||
++inVectorPtr;
|
||||
outputVector1 = _mm_shuffle_epi8(srcVector2, shuffleMask1);
|
||||
outputVector2 = _mm_shuffle_epi8(srcVector1, shuffleMask2);
|
||||
outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 8);
|
||||
_mm_store_si128(dstVectorPtr, outputVector);
|
||||
++dstVectorPtr;
|
||||
|
||||
srcVector2 = _mm_loadu_si128(inVectorPtr);
|
||||
++inVectorPtr;
|
||||
outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1);
|
||||
outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2);
|
||||
outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 12);
|
||||
_mm_store_si128(dstVectorPtr, outputVector);
|
||||
++dstVectorPtr;
|
||||
}
|
||||
dst24 = reinterpret_cast<quint24*>(dstVectorPtr);
|
||||
src = reinterpret_cast<const uint*>(inVectorPtr);
|
||||
|
||||
SIMD_EPILOGUE(i, len, 15)
|
||||
*dst24++ = quint24(*src++);
|
||||
}
|
||||
|
||||
void QT_FASTCALL storePixelsBPP24_ssse3(uchar *dest, const uint *src, int index, int count)
|
||||
{
|
||||
store_uint24_ssse3(dest + index * 3, src, count);
|
||||
const quint24 *s = reinterpret_cast<const quint24 *>(src);
|
||||
for (int i = 0; i < count; ++i)
|
||||
buffer[i] = s[index + i];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
extern void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len);
|
||||
|
|
|
|||
Loading…
Reference in New Issue