summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-12-07 10:03:42 +0100
committerSamuel Rødal <sroedal@trolltech.com>2009-12-14 15:18:36 +0100
commit9c4a79038fcd2c2a90a277db81aaadac50eaa59a (patch)
tree05af6d76da4c120341d784b6e18671d769025652 /src/gui
parentb543f356ca9f4a1db72e937968f06804df7c17bd (diff)
downloadqt4-tools-9c4a79038fcd2c2a90a277db81aaadac50eaa59a.tar.gz
Optimized blur / drop shadow effects for the GL 2 paint engine.
Do the blur in half the resolution in software and then upload the result as a texture and smooth-scale it on the GPU. This leads to stable and decent performance regardless of the blur radius, and simplifies the implementation quite a bit. Reviewed-by: Bjørn Erik Nilsen
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/effects/qgraphicseffect.cpp11
-rw-r--r--src/gui/image/qpixmapfilter.cpp17
-rw-r--r--src/gui/painting/qmemrotate.cpp21
-rw-r--r--src/gui/painting/qmemrotate_p.h2
4 files changed, 39 insertions, 12 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index dafea528af..a523bab6b7 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -844,22 +844,19 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
void QGraphicsBlurEffect::draw(QPainter *painter)
{
Q_D(QGraphicsBlurEffect);
- if (d->filter->radius() <= 0) {
+ if (d->filter->radius() < 1) {
drawSource(painter);
return;
}
PixmapPadMode mode = PadToEffectiveBoundingRect;
if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
- mode = PadToTransparentBorder;
+ mode = NoPad;
// Draw pixmap in device coordinates to avoid pixmap scaling.
QPoint offset;
- const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
- QTransform restoreTransform = painter->worldTransform();
- painter->setWorldTransform(QTransform());
+ QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode);
d->filter->draw(painter, offset, pixmap);
- painter->setWorldTransform(restoreTransform);
}
/*!
@@ -1040,7 +1037,7 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter)
PixmapPadMode mode = PadToEffectiveBoundingRect;
if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
- mode = PadToTransparentBorder;
+ mode = NoPad;
// Draw pixmap in device coordinates to avoid pixmap scaling.
QPoint offset;
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 6289efeadb..9c7c28e5f2 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -627,7 +627,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
{
// halve the radius if we're using two passes
if (improvedQuality)
- radius *= 0.5;
+ radius *= qreal(0.5);
Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied
|| img.format() == QImage::Format_RGB32);
@@ -638,7 +638,7 @@ void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transp
const qreal cutOffIntensity = 2;
int alpha = radius <= qreal(1e-5)
? ((1 << aprec)-1)
- : qRound((1<<aprec)*(1 - qPow(cutOffIntensity / 255, 1 / radius)));
+ : qRound((1<<aprec)*(1 - qPow(cutOffIntensity * (1 / qreal(255)), 1 / radius)));
int img_height = img.height();
for (int row = 0; row < img_height; ++row) {
@@ -873,7 +873,7 @@ Q_GUI_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, boo
if (radius >= 4) {
blurImage = qt_halfScaled(blurImage);
scale = 2;
- radius *= 0.5;
+ radius *= qreal(0.5);
}
if (alphaOnly)
@@ -896,6 +896,8 @@ Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, in
expblur<12, 10, false>(blurImage, radius, quality, transposed);
}
+bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
+
/*!
\internal
*/
@@ -914,11 +916,16 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap
return;
}
+ qreal scaledRadius = radiusScale * d->radius;
+ qreal scale;
+ if (qt_scaleForTransform(painter->transform(), &scale))
+ scaledRadius /= scale;
+
QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ?
static_cast<QPaintEngineEx *>(painter->paintEngine())->pixmapFilter(type(), this) : 0;
QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter);
if (blurFilter) {
- blurFilter->setRadius(radiusScale * d->radius);
+ blurFilter->setRadius(scaledRadius);
blurFilter->setBlurHints(d->hints);
blurFilter->draw(painter, p, src, srcRect);
return;
@@ -936,7 +943,7 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap
QTransform transform = painter->worldTransform();
painter->translate(p);
- qt_blurImage(painter, srcImage, radiusScale * d->radius, (d->hints & QGraphicsBlurEffect::QualityHint), false);
+ qt_blurImage(painter, srcImage, scaledRadius, (d->hints & QGraphicsBlurEffect::QualityHint), false);
painter->setWorldTransform(transform);
}
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 67dc2c7954..e3a6f78d45 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -572,5 +572,26 @@ QT_IMPL_MEMROTATE(quint32, qrgb_generic16)
QT_IMPL_MEMROTATE(quint16, qrgb_generic16)
#endif
+struct qrgb_gl_rgba
+{
+public:
+ inline qrgb_gl_rgba(quint32 v) {
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ data = ((v << 16) & 0xff0000) | ((v >> 16) & 0xff) | (v & 0xff00ff00);
+ else
+ data = (v << 8) | ((v >> 24) & 0xff);
+ }
+
+ inline operator quint32() const { return data; }
+
+private:
+ quint32 data;
+} Q_PACKED;
+
+void Q_GUI_EXPORT qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride,
+ quint32 *dest, int dstStride)
+{
+ qt_memrotate90_template(src, srcWidth, srcHeight, srcStride, reinterpret_cast<qrgb_gl_rgba *>(dest), dstStride);
+}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 676a880cdf..8aee575fca 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -81,6 +81,8 @@ QT_BEGIN_NAMESPACE
void Q_GUI_QWS_EXPORT qt_memrotate180(const srctype*, int, int, int, desttype*, int); \
void Q_GUI_QWS_EXPORT qt_memrotate270(const srctype*, int, int, int, desttype*, int)
+void Q_GUI_EXPORT qt_memrotate90(const quint32*, int, int, int, quint32*, int);
+
QT_DECL_MEMROTATE(quint32, quint32);
QT_DECL_MEMROTATE(quint32, quint16);
QT_DECL_MEMROTATE(quint16, quint32);