From 10e1d939d6bf08249304cb2c555be2f74c3a0f02 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 16 Sep 2009 11:46:41 +1000 Subject: Reduce overhead of paint engine-specific pixmap filters Engine-specific pixmap filters were being created, used, and destroyed every time draw() was called on QPixmapColorizeFilter, QPixmapBlurFilter, and so on. This had a heavy performance penalty and made it difficult for the GL paint engine to cache shaders from one request to the next. A generic filter can request an engine-specific filter that matches its parameters. The engine can either create a new one or return a previously allocated filter object. Ownership of engine-specific pixmap filter objects is moved to the paint engine itself. Reviewed-by: Andrew den Exter Reviewed-by: Michael Brasser Reviewed-by: Michael Goddard Reviewed-by: Sarah Smith --- src/gui/image/qpixmapfilter.cpp | 9 ++--- src/gui/painting/qpaintengineex_p.h | 7 +++- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 8 ----- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 7 +++- src/opengl/qgl_p.h | 2 -- src/opengl/qglpixmapfilter.cpp | 21 +++++++----- src/openvg/qpaintengine_vg.cpp | 38 +++++++++++++++------- src/openvg/qpaintengine_vg_p.h | 2 +- 8 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 4fa2e6c..4fb650f 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -418,13 +418,12 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q return; QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? - static_cast(painter->paintEngine())->createPixmapFilter(type()) : 0; + static_cast(painter->paintEngine())->pixmapFilter(type(), this) : 0; QPixmapConvolutionFilter *convolutionFilter = static_cast(filter); if (convolutionFilter) { convolutionFilter->setConvolutionKernel(d->convolutionKernel, d->kernelWidth, d->kernelHeight); convolutionFilter->d_func()->convoluteAlpha = d->convoluteAlpha; convolutionFilter->draw(painter, p, src, srcRect); - delete convolutionFilter; return; } @@ -669,13 +668,12 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap } QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? - static_cast(painter->paintEngine())->createPixmapFilter(type()) : 0; + static_cast(painter->paintEngine())->pixmapFilter(type(), this) : 0; QPixmapBlurFilter *blurFilter = static_cast(filter); if (blurFilter) { blurFilter->setRadius(d->radius); blurFilter->setQuality(d->quality); blurFilter->draw(painter, p, src, srcRect); - delete blurFilter; return; } @@ -836,13 +834,12 @@ void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const Q { Q_D(const QPixmapColorizeFilter); QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? - static_cast(painter->paintEngine())->createPixmapFilter(type()) : 0; + static_cast(painter->paintEngine())->pixmapFilter(type(), this) : 0; QPixmapColorizeFilter *colorizeFilter = static_cast(filter); if (colorizeFilter) { colorizeFilter->setColor(d->color); colorizeFilter->setStrength(d->strength); colorizeFilter->draw(painter, dest, src, srcRect); - delete colorizeFilter; return; } diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 9f0d84a..a12a71f 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -207,7 +207,12 @@ public: virtual void beginNativePainting() {} virtual void endNativePainting() {} - virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; } + // Return a pixmap filter of "type" that can render the parameters + // in "prototype". The returned filter is owned by the engine and + // will be destroyed when the engine is destroyed. The "prototype" + // allows the engine to pick different filters based on the parameters + // that will be requested, and not just the "type". + virtual QPixmapFilter *pixmapFilter(int /*type*/, const QPixmapFilter * /*prototype*/) { return 0; } // These flags are needed in the implementation of paint buffers. enum Flags diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e41d0b4..2ee92c3 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1769,14 +1769,6 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() { } -QPixmapFilter *QGL2PaintEngineEx::createPixmapFilter(int type) const -{ - const QGLContext *ctx = QGLContext::currentContext(); - if (ctx) - return ctx->d_func()->createPixmapFilter(type); - return 0; -} - QT_END_NAMESPACE #include "qpaintengineex_opengl2.moc" diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 34f4eb8..a44be90 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -59,6 +59,7 @@ #include #include #include +#include enum EngineMode { ImageDrawingMode, @@ -140,7 +141,7 @@ public: const QGLContext* context(); - QPixmapFilter *createPixmapFilter(int type) const; + QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); void setRenderTextActive(bool); @@ -264,6 +265,10 @@ public: bool inRenderText; float textureInvertedY; + + QScopedPointer convolutionFilter; + QScopedPointer colorizeFilter; + QScopedPointer blurFilter; }; QT_END_NAMESPACE diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 2b74e69..7269195 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -352,8 +352,6 @@ public: #endif static void setCurrentContext(QGLContext *context); - - QPixmapFilter *createPixmapFilter(int type) const; }; // ### make QGLContext a QObject in 5.0 and remove the proxy stuff diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 43f1990..b48c497 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -123,23 +123,28 @@ private: extern QGLWidget *qt_gl_share_widget(); -QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const +QPixmapFilter *QGL2PaintEngineEx::pixmapFilter(int type, const QPixmapFilter *prototype) { + Q_D(QGL2PaintEngineEx); switch (type) { case QPixmapFilter::ColorizeFilter: - return new QGLPixmapColorizeFilter; + if (!d->colorizeFilter) + d->colorizeFilter.reset(new QGLPixmapColorizeFilter); + return d->colorizeFilter.data(); case QPixmapFilter::BlurFilter: - return new QGLPixmapBlurFilter; + if (!d->blurFilter) + d->blurFilter.reset(new QGLPixmapBlurFilter); + return d->blurFilter.data(); case QPixmapFilter::ConvolutionFilter: - return new QGLPixmapConvolutionFilter; + if (!d->convolutionFilter) + d->convolutionFilter.reset(new QGLPixmapConvolutionFilter); + return d->convolutionFilter.data(); - default: - return 0; - break; + default: break; } - return 0; + return QPaintEngineEx::pixmapFilter(type, prototype); } extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array); diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 972f4a1..d87ac40 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -211,6 +211,11 @@ public: QVGFontEngineCleaner *fontEngineCleaner; #endif + QScopedPointer convolutionFilter; + QScopedPointer colorizeFilter; + QScopedPointer dropShadowFilter; + QScopedPointer blurFilter; + // Ensure that the path transform is properly set in the VG context // before we perform a vgDrawPath() operation. inline void ensurePathTransform() @@ -3110,20 +3115,31 @@ void QVGPaintEngine::endNativePainting() vgSetPaint(d->brushPaint, VG_FILL_PATH); } -QPixmapFilter *QVGPaintEngine::createPixmapFilter(int type) const +QPixmapFilter *QVGPaintEngine::pixmapFilter(int type, const QPixmapFilter *prototype) { #if !defined(QT_SHIVAVG) - if (type == QPixmapFilter::ConvolutionFilter) - return new QVGPixmapConvolutionFilter; - else if (type == QPixmapFilter::ColorizeFilter) - return new QVGPixmapColorizeFilter; - else if (type == QPixmapFilter::DropShadowFilter) - return new QVGPixmapDropShadowFilter; - else if (type == QPixmapFilter::BlurFilter) - return new QVGPixmapBlurFilter; - else + Q_D(QVGPaintEngine); + switch (type) { + case QPixmapFilter::ConvolutionFilter: + if (!d->convolutionFilter) + d->convolutionFilter.reset(new QVGPixmapConvolutionFilter); + return d->convolutionFilter.data(); + case QPixmapFilter::ColorizeFilter: + if (!d->colorizeFilter) + d->colorizeFilter.reset(new QVGPixmapColorizeFilter); + return d->colorizeFilter.data(); + case QPixmapFilter::DropShadowFilter: + if (!d->dropShadowFilter) + d->dropShadowFilter.reset(new QVGPixmapDropShadowFilter); + return d->dropShadowFilter.data(); + case QPixmapFilter::BlurFilter: + if (!d->blurFilter) + d->blurFilter.reset(new QVGPixmapBlurFilter); + return d->blurFilter.data(); + default: break; + } #endif - return QPaintEngineEx::createPixmapFilter(type); + return QPaintEngineEx::pixmapFilter(type, prototype); } void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty) diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 4ae06bc..5c0f525 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -143,7 +143,7 @@ public: void beginNativePainting(); void endNativePainting(); - QPixmapFilter *createPixmapFilter(int type) const; + QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); QVGPaintEnginePrivate *vgPrivate() { Q_D(QVGPaintEngine); return d; } -- cgit v0.12