summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qblittable_p.h2
-rw-r--r--src/gui/painting/qdrawhelper.cpp157
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp33
-rw-r--r--src/gui/painting/qpainter.cpp18
-rw-r--r--src/gui/painting/qvectorpath_p.h28
6 files changed, 203 insertions, 37 deletions
diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h
index 159e60079f..f65549d63c 100644
--- a/src/gui/painting/qblittable_p.h
+++ b/src/gui/painting/qblittable_p.h
@@ -68,7 +68,7 @@ public:
// Internal ones
OutlineCapability = 0x0001000
};
- Q_DECLARE_FLAGS (Capabilities, Capability);
+ Q_DECLARE_FLAGS (Capabilities, Capability)
QBlittable(const QSize &size, Capabilities caps);
virtual ~QBlittable();
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 7a5c5dc660..b5ccafdf9a 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1709,6 +1709,163 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
}
} else {
//we are zooming less than 8x, use 4bit precision
+
+ if (blendType != BlendTransformedBilinearTiled) {
+#define BILINEAR_ROTATE_BOUNDS_PROLOG \
+ while (b < end) { \
+ int x1 = (fx >> 16); \
+ int x2; \
+ int y1 = (fy >> 16); \
+ int y2; \
+ fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \
+ fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); \
+ if (x1 != x2 && y1 != y2) \
+ break; \
+ const uint *s1 = (const uint *)data->texture.scanLine(y1); \
+ const uint *s2 = (const uint *)data->texture.scanLine(y2); \
+ uint tl = s1[x1]; \
+ uint tr = s1[x2]; \
+ uint bl = s2[x1]; \
+ uint br = s2[x2]; \
+ int distx = (fx & 0x0000ffff) >> 12; \
+ int disty = (fy & 0x0000ffff) >> 12; \
+ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \
+ fx += fdx; \
+ fy += fdy; \
+ ++b; \
+ } \
+ uint *boundedEnd = end - 3; \
+ boundedEnd -= 3;
+
+#if defined(__SSE2__)
+ BILINEAR_ROTATE_BOUNDS_PROLOG
+
+ const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
+ const __m128i v_256 = _mm_set1_epi16(256);
+ __m128i v_fdx = _mm_set1_epi32(fdx*4);
+ __m128i v_fdy = _mm_set1_epi32(fdy*4);
+
+ const uchar *textureData = data->texture.imageData;
+ const int bytesPerLine = data->texture.bytesPerLine;
+
+ union Vect_buffer { __m128i vect; qint32 i[4]; };
+ Vect_buffer v_fx, v_fy;
+
+ for (int i = 0; i < 4; i++) {
+ v_fx.i[i] = fx;
+ v_fy.i[i] = fy;
+ fx += fdx;
+ fy += fdy;
+ }
+
+ while (b < boundedEnd) {
+ if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
+ break;
+ if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
+ break;
+ if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
+ break;
+ if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
+ break;
+
+ Vect_buffer tl, tr, bl, br;
+ Vect_buffer v_fx_shifted, v_fy_shifted;
+ v_fx_shifted.vect = _mm_srli_epi32(v_fx.vect, 16);
+ v_fy_shifted.vect = _mm_srli_epi32(v_fy.vect, 16);
+
+ for (int i = 0; i < 4; i++) {
+ const int x1 = v_fx_shifted.i[i];
+ const int y1 = v_fy_shifted.i[i];
+ const uchar *sl = textureData + bytesPerLine * y1;
+ const uint *s1 = (const uint *)sl;
+ const uint *s2 = (const uint *)(sl + bytesPerLine);
+ tl.i[i] = s1[x1];
+ tr.i[i] = s1[x1+1];
+ bl.i[i] = s2[x1];
+ br.i[i] = s2[x1+1];
+ }
+ __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12);
+ __m128i v_disty = _mm_srli_epi16(v_fy.vect, 12);
+ v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
+ v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0));
+ v_disty = _mm_shufflehi_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
+ v_disty = _mm_shufflelo_epi16(v_disty, _MM_SHUFFLE(2,2,0,0));
+
+ interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b);
+ b+=4;
+ v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx);
+ v_fy.vect = _mm_add_epi32(v_fy.vect, v_fdy);
+ }
+ fx = v_fx.i[0];
+ fy = v_fy.i[0];
+#elif defined(__ARM_NEON__)
+ BILINEAR_ROTATE_BOUNDS_PROLOG
+
+ const int16x8_t colorMask = vdupq_n_s16(0x00ff);
+ const int16x8_t invColorMask = vmvnq_s16(colorMask);
+ const int16x8_t v_256 = vdupq_n_s16(256);
+ int32x4_t v_fdx = vdupq_n_s32(fdx*4);
+ int32x4_t v_fdy = vdupq_n_s32(fdy*4);
+
+ const uchar *textureData = data->texture.imageData;
+ const int bytesPerLine = data->texture.bytesPerLine;
+
+ union Vect_buffer { int32x4_t vect; quint32 i[4]; };
+ Vect_buffer v_fx, v_fy;
+
+ for (int i = 0; i < 4; i++) {
+ v_fx.i[i] = fx;
+ v_fy.i[i] = fy;
+ fx += fdx;
+ fy += fdy;
+ }
+
+ const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff);
+
+ while (b < boundedEnd) {
+ if (fdx > 0 && (v_fx.i[3] >> 16) >= image_x2)
+ break;
+ if (fdx < 0 && (v_fx.i[3] >> 16) < image_x1)
+ break;
+ if (fdy > 0 && (v_fy.i[3] >> 16) >= image_y2)
+ break;
+ if (fdy < 0 && (v_fy.i[3] >> 16) < image_y1)
+ break;
+
+ Vect_buffer tl, tr, bl, br;
+
+ Vect_buffer v_fx_shifted, v_fy_shifted;
+ v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16);
+ v_fy_shifted.vect = vshrq_n_s32(v_fy.vect, 16);
+
+ for (int i = 0; i < 4; i++) {
+ const int x1 = v_fx_shifted.i[i];
+ const int y1 = v_fy_shifted.i[i];
+ const uchar *sl = textureData + bytesPerLine * y1;
+ const uint *s1 = (const uint *)sl;
+ const uint *s2 = (const uint *)(sl + bytesPerLine);
+ tl.i[i] = s1[x1];
+ tr.i[i] = s1[x1+1];
+ bl.i[i] = s2[x1];
+ br.i[i] = s2[x1+1];
+ }
+
+ int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12);
+ int32x4_t v_disty = vshrq_n_s32(vandq_s32(v_fy.vect, v_ffff_mask), 12);
+ v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16));
+ v_disty = vorrq_s32(v_disty, vshlq_n_s32(v_disty, 16));
+ int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4);
+
+ interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b);
+ b+=4;
+ v_fx.vect = vaddq_s32(v_fx.vect, v_fdx);
+ v_fy.vect = vaddq_s32(v_fy.vect, v_fdy);
+ }
+ fx = v_fx.i[0];
+ fy = v_fy.i[0];
+#endif
+ }
+
while (b < end) {
int x1 = (fx >> 16);
int x2;
diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp
index 26eacacd49..67a692e2db 100644
--- a/src/gui/painting/qpaintengine_blitter.cpp
+++ b/src/gui/painting/qpaintengine_blitter.cpp
@@ -238,7 +238,7 @@ private:
class QBlitterPaintEnginePrivate : public QRasterPaintEnginePrivate
{
- Q_DECLARE_PUBLIC(QBlitterPaintEngine);
+ Q_DECLARE_PUBLIC(QBlitterPaintEngine)
public:
QBlitterPaintEnginePrivate(QBlittablePlatformPixmap *p)
: QRasterPaintEnginePrivate()
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index bfcb24ae3a..ce8c1d1ca7 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -235,21 +235,6 @@ static const QRectF boundingRect(const QPointF *points, int pointCount)
}
#endif
-template <typename T> static inline bool isRect(const T *pts, int elementCount) {
- return (elementCount == 5 // 5-point polygon, check for closed rect
- && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point
- && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
- && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
- && pts[0] < pts[4] && pts[1] < pts[5]
- ) ||
- (elementCount == 4 // 4-point polygon, check for unclosed rect
- && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
- && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
- && pts[0] < pts[4] && pts[1] < pts[5]
- );
-}
-
-
static void qt_ft_outline_move_to(qfixed x, qfixed y, void *data)
{
((QOutlineMapper *) data)->moveTo(QPointF(qt_fixed_to_real(x), qt_fixed_to_real(y)));
@@ -1193,22 +1178,14 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- const qreal *points = path.points();
- const QPainterPath::ElementType *types = path.elements();
-
// There are some cases that are not supported by clip(QRect)
if (op != Qt::IntersectClip || !s->clip || s->clip->hasRectClip || s->clip->hasRegionClip) {
if (s->matrix.type() <= QTransform::TxScale
- && ((path.shape() == QVectorPath::RectangleHint)
- || (isRect(points, path.elementCount())
- && (!types || (types[0] == QPainterPath::MoveToElement
- && types[1] == QPainterPath::LineToElement
- && types[2] == QPainterPath::LineToElement
- && types[3] == QPainterPath::LineToElement))))) {
+ && path.isRect()) {
#ifdef QT_DEBUG_DRAW
qDebug() << " --- optimizing vector clip to rect clip...";
#endif
-
+ const qreal *points = path.points();
QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toRect(), op))
return;
@@ -1939,7 +1916,7 @@ void QRasterPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
#endif
Q_ASSERT(pointCount >= 2);
- if (mode != PolylineMode && isRect((qreal *) points, pointCount)) {
+ if (mode != PolylineMode && QVectorPath::isRect((qreal *) points, pointCount)) {
QRectF r(points[0], points[2]);
drawRects(&r, 1);
return;
@@ -1980,7 +1957,7 @@ void QRasterPaintEngine::drawPolygon(const QPoint *points, int pointCount, Polyg
qDebug() << " - " << points[i];
#endif
Q_ASSERT(pointCount >= 2);
- if (mode != PolylineMode && isRect((int *) points, pointCount)) {
+ if (mode != PolylineMode && QVectorPath::isRect((int *) points, pointCount)) {
QRect r(points[0].x(),
points[0].y(),
points[2].x() - points[0].x(),
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index fe5fc051df..3f387d575b 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -147,8 +147,9 @@ static inline uint line_emulation(uint emulation)
}
#ifndef QT_NO_DEBUG
-static bool qt_painter_thread_test(int devType, const char *what)
+static bool qt_painter_thread_test(int devType, int engineType, const char *what)
{
+ const QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
switch (devType) {
case QInternal::Image:
case QInternal::Printer:
@@ -157,8 +158,13 @@ static bool qt_painter_thread_test(int devType, const char *what)
break;
default:
if (QThread::currentThread() != qApp->thread()
- && (devType!=QInternal::Pixmap || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps))
- && (devType!=QInternal::OpenGL || !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))) {
+ // pixmaps cannot be targets unless threaded pixmaps are supported
+ && (devType != QInternal::Pixmap || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedPixmaps))
+ // framebuffer objects and such cannot be targets unless threaded GL is supported
+ && (devType != QInternal::OpenGL || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL))
+ // widgets cannot be targets except for QGLWidget
+ && (devType != QInternal::Widget || !platformIntegration->hasCapability(QPlatformIntegration::ThreadedOpenGL)
+ || (engineType != QPaintEngine::OpenGL && engineType != QPaintEngine::OpenGL2))) {
qWarning("QPainter: It is not safe to use %s outside the GUI thread", what);
return false;
}
@@ -5054,7 +5060,7 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
if (d->extended) {
@@ -5125,7 +5131,7 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
if (!d->engine || pm.isNull())
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawPixmap()");
#endif
qreal x = r.x();
@@ -6610,7 +6616,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo
return;
#ifndef QT_NO_DEBUG
- qt_painter_thread_test(d->device->devType(), "drawTiledPixmap()");
+ qt_painter_thread_test(d->device->devType(), d->engine->type(), "drawTiledPixmap()");
#endif
qreal sw = pixmap.width();
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index e97d6e1dce..ca95c32597 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -167,6 +167,32 @@ public:
return 0;
}
+ template <typename T> static inline bool isRect(const T *pts, int elementCount) {
+ return (elementCount == 5 // 5-point polygon, check for closed rect
+ && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point
+ && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
+ && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
+ && pts[0] < pts[4] && pts[1] < pts[5]
+ ) ||
+ (elementCount == 4 // 4-point polygon, check for unclosed rect
+ && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
+ && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
+ && pts[0] < pts[4] && pts[1] < pts[5]
+ );
+ }
+
+ inline bool isRect() const
+ {
+ const QPainterPath::ElementType * const types = elements();
+
+ return (shape() == QVectorPath::RectangleHint)
+ || (isRect(points(), elementCount())
+ && (!types || (types[0] == QPainterPath::MoveToElement
+ && types[1] == QPainterPath::LineToElement
+ && types[2] == QPainterPath::LineToElement
+ && types[3] == QPainterPath::LineToElement)));
+ }
+
private:
Q_DISABLE_COPY(QVectorPath)