diff options
-rw-r--r-- | src/declarative/canvas/qsimplecanvas_opengl.cpp | 84 | ||||
-rw-r--r-- | src/declarative/canvas/qsimplecanvas_p.h | 3 | ||||
-rw-r--r-- | src/declarative/canvas/qsimplecanvasitem.h | 23 | ||||
-rw-r--r-- | src/declarative/fx/qfximage.cpp | 57 | ||||
-rw-r--r-- | src/declarative/fx/qfximage_p.h | 4 | ||||
-rw-r--r-- | src/declarative/fx/qfxrect.cpp | 126 | ||||
-rw-r--r-- | src/declarative/fx/qfxrect_p.h | 4 |
7 files changed, 221 insertions, 80 deletions
diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp index 659104d..7969a2a 100644 --- a/src/declarative/canvas/qsimplecanvas_opengl.cpp +++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp @@ -294,7 +294,7 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) } } -//#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING +#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING QRectF QSimpleCanvasItemPrivate::setupPainting(int version, int &z, QSimpleCanvasItem **opaqueList) { static QRectF scene(-1., -1., 2., 2.); @@ -595,4 +595,86 @@ void QSimpleCanvasItem::GLPainter::fillRect(const QRectF &rect, glEnable(GL_BLEND); } +void QSimpleCanvasItem::CachedTexture::addRef() +{ + ++r; +} + +void QSimpleCanvasItem::CachedTexture::release() +{ + Q_ASSERT(r > 0); + --r; + + if (r == 0) { + if (!s.isEmpty()) + d->cachedTextures.remove(s); + delete this; + } +} + +int QSimpleCanvasItem::CachedTexture::pixmapWidth() const +{ + return w; +} + +int QSimpleCanvasItem::CachedTexture::pixmapHeight() const +{ + return h; +} + +QSimpleCanvasItem::CachedTexture::CachedTexture() +: r(0), w(0), h(0) +{ +} + +QSimpleCanvasItem::CachedTexture * +QSimpleCanvasItem::cachedTexture(const QString &key) +{ + Q_D(QSimpleCanvasItem); + if (!d->canvas || key.isEmpty()) + return 0; + + QSimpleCanvasPrivate *canvas = d->canvas->d; + QHash<QString, QSimpleCanvasItem::CachedTexture *>::ConstIterator iter = + canvas->cachedTextures.find(key); + if (iter != canvas->cachedTextures.end()) { + (*iter)->addRef(); + return (*iter); + } else { + return 0; + } +} + +QSimpleCanvasItem::CachedTexture * +QSimpleCanvasItem::cachedTexture(const QString &key, const QPixmap &pix) +{ + Q_D(QSimpleCanvasItem); + if (!d->canvas) + return 0; + + QSimpleCanvasPrivate *canvas = d->canvas->d; + QHash<QString, QSimpleCanvasItem::CachedTexture *>::ConstIterator iter = + canvas->cachedTextures.end(); + if (!key.isEmpty()) + iter = canvas->cachedTextures.find(key); + + if (iter != canvas->cachedTextures.end()) { + (*iter)->addRef(); + return (*iter); + } else { + CachedTexture *rv = new CachedTexture; + rv->s = key; + rv->d = canvas; + rv->w = pix.width(); + rv->h = pix.height(); + rv->setImage(pix.toImage(), GLTexture::PowerOfTwo); + rv->setHorizontalWrap(GLTexture::Repeat); + rv->setVerticalWrap(GLTexture::Repeat); + rv->addRef(); + if (!key.isEmpty()) + canvas->cachedTextures.insert(key, rv); + return rv; + } +} + QT_END_NAMESPACE diff --git a/src/declarative/canvas/qsimplecanvas_p.h b/src/declarative/canvas/qsimplecanvas_p.h index 5fc0c48..3a0186e 100644 --- a/src/declarative/canvas/qsimplecanvas_p.h +++ b/src/declarative/canvas/qsimplecanvas_p.h @@ -43,6 +43,7 @@ #define QSIMPLECANVAS_P_H #include "qsimplecanvas.h" +#include "qsimplecanvasitem.h" #include <qstack.h> #include <qdatetime.h> @@ -187,6 +188,8 @@ public: } mutable GLBasicShaders *basicShadersInstance; + QHash<QString, QSimpleCanvasItem::CachedTexture *> cachedTextures; + QList<QGLFramebufferObject *> frameBuffers; QGLFramebufferObject *acquire(int, int); void release(QGLFramebufferObject *); diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index ee07a21..e62c56d 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -45,6 +45,7 @@ #include <QtDeclarative/qfxglobal.h> #include <QtDeclarative/qmldebuggerstatus.h> #include <QtDeclarative/qsimplecanvas.h> +#include <QtDeclarative/gltexture.h> #include <QtCore/qobject.h> #include <QtGui/qgraphicsitem.h> @@ -236,6 +237,28 @@ public: static QSimpleCanvasItem *findNextFocus(QSimpleCanvasItem *item); GLBasicShaders *basicShaders() const; + +#if defined(QFX_RENDER_OPENGL) + class CachedTexture : public GLTexture + { + public: + void addRef(); + void release(); + + int pixmapWidth() const; + int pixmapHeight() const; + + private: + CachedTexture(); + friend class QSimpleCanvasItem; + QSimpleCanvasPrivate *d; + QString s; + int r, w, h; + }; + + CachedTexture *cachedTexture(const QString &); + CachedTexture *cachedTexture(const QString &, const QPixmap &); +#endif static QPixmap string(const QString &, const QColor & = Qt::black, const QFont & = QFont()); diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 509323a..03a674d 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -124,9 +124,13 @@ QFxImage::QFxImage(QFxImagePrivate &dd, QFxItem *parent) QFxImage::~QFxImage() { - Q_D(const QFxImage); + Q_D(QFxImage); if (d->sciReply) d->sciReply->deleteLater(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } } /*! @@ -156,7 +160,10 @@ void QFxImage::setPixmap(const QPixmap &pix) #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif update(); } @@ -440,7 +447,7 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, vertices[4] = 0; vertices[5] = 0; vertices[6] = widthV; vertices[7] = 0; - *texture = &d->tex; + *texture = d->tex; if (d->tiled) { float tileWidth = widthV / d->pix.width(); @@ -451,9 +458,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, texVertices[6] = tileWidth; texVertices[7] = tileHeight; } else { texVertices[0] = 0; texVertices[1] = 0; - texVertices[2] = d->tex.glWidth(); texVertices[3] = 0; - texVertices[4] = 0; texVertices[5] = d->tex.glHeight(); - texVertices[6] = d->tex.glWidth(); texVertices[7] = d->tex.glHeight(); + texVertices[2] = d->tex->glWidth(); texVertices[3] = 0; + texVertices[4] = 0; texVertices[5] = d->tex->glHeight(); + texVertices[6] = d->tex->glWidth(); texVertices[7] = d->tex->glHeight(); } return 8; @@ -461,11 +468,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, void QFxImagePrivate::checkDirty() { - if (texDirty && !pix.isNull()) { - tex.setImage(pix.toImage(), GLTexture::PowerOfTwo); - tex.setHorizontalWrap(GLTexture::Repeat); - tex.setVerticalWrap(GLTexture::Repeat); - } + Q_Q(QFxImage); + if (texDirty && !pix.isNull()) + tex = q->cachedTexture(url.toString(), pix); texDirty = false; } @@ -492,8 +497,8 @@ void QFxImage::paintGLContents(GLPainter &p) float widthV = width(); float heightV = height(); - float glWidth = d->tex.glWidth(); - float glHeight = d->tex.glHeight(); + float glWidth = d->tex->glWidth(); + float glHeight = d->tex->glHeight(); float vert[] = { 0, heightV, @@ -516,7 +521,7 @@ void QFxImage::paintGLContents(GLPainter &p) shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex, 2); - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex->texture()); glDrawArrays(GL_TRIANGLES, 0, 6); } else { @@ -548,8 +553,8 @@ void QFxImage::paintGLContents(GLPainter &p) float heightV = height(); float texleft = 0; - float texright = d->tex.glWidth(); - float textop = d->tex.glHeight(); + float texright = d->tex->glWidth(); + float textop = d->tex->glHeight(); float texbottom = 0; float imgleft = 0; float imgright = widthV; @@ -562,19 +567,19 @@ void QFxImage::paintGLContents(GLPainter &p) const int sgb = d->scaleGrid->bottom(); if (sgl) { - texleft = d->tex.glWidth() * float(sgl) / imgWidth; + texleft = d->tex->glWidth() * float(sgl) / imgWidth; imgleft = sgl; } if (sgr) { - texright = d->tex.glWidth() - float(sgr) / imgWidth; + texright = d->tex->glWidth() - float(sgr) / imgWidth; imgright = widthV - sgr; } if (sgt) { - textop = d->tex.glHeight() - float(sgb) / imgHeight; + textop = d->tex->glHeight() - float(sgb) / imgHeight; imgtop = sgt; } if (sgb) { - texbottom = d->tex.glHeight() * float(sgt) / imgHeight; + texbottom = d->tex->glHeight() * float(sgt) / imgHeight; imgbottom = heightV - sgb; } @@ -722,7 +727,7 @@ void QFxImage::paintGLContents(GLPainter &p) 1, texbottom, 1, 0 }; - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); + glBindTexture(GL_TEXTURE_2D, d->tex->texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); @@ -847,7 +852,10 @@ void QFxImage::setSource(const QString &url) setImplicitHeight(0); #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif emit statusChanged(d->status); emit sourceChanged(d->source); @@ -908,7 +916,10 @@ void QFxImage::requestFinished() d->progress = 1.0; #if defined(QFX_RENDER_OPENGL) d->texDirty = true; - d->tex.clear(); + if (d->tex) { + d->tex->release(); + d->tex = 0; + } #endif emit statusChanged(d->status); emit sourceChanged(d->source); diff --git a/src/declarative/fx/qfximage_p.h b/src/declarative/fx/qfximage_p.h index b5c6055..cd07a37 100644 --- a/src/declarative/fx/qfximage_p.h +++ b/src/declarative/fx/qfximage_p.h @@ -74,7 +74,7 @@ public: QFxImagePrivate() : scaleGrid(0), tiled(false), smooth(false), opaque(false), #if defined(QFX_RENDER_OPENGL) - texDirty(true), + texDirty(true), tex(0), #endif status(QFxImage::Idle), sciReply(0), progress(0.0) { @@ -102,7 +102,7 @@ public: #if defined(QFX_RENDER_OPENGL) bool texDirty : 1; void checkDirty(); - GLTexture tex; + QSimpleCanvasItem::CachedTexture *tex; #endif QFxImage::Status status; diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index d52e31c..eacc85e 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -257,7 +257,10 @@ void QFxRect::doUpdate() #endif #if defined(QFX_RENDER_OPENGL) Q_D(QFxRect); - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; setPaintMargin((pw+1)/2); @@ -361,7 +364,10 @@ void QFxRect::setRadius(qreal radius) #if defined(QFX_RENDER_QPAINTER) d->rectImage = QPixmap(); #elif defined(QFX_RENDER_OPENGL) - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif update(); } @@ -408,7 +414,10 @@ void QFxRect::setColor(const QColor &c) d->rectImage = QPixmap(); #endif #if defined(QFX_RENDER_OPENGL) - d->rectTexture.clear(); + if (d->rectTexture) { + d->rectTexture->release(); + d->rectTexture = 0; + } #endif update(); } @@ -521,42 +530,55 @@ void QFxRect::generateBorderedRect() void QFxRect::generateRoundedRect() { Q_D(QFxRect); - if (d->rectTexture.isNull()) { + if (!d->rectTexture) { const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; - QImage roundRect(d->radius*2 + 4 + pw*2, d->radius*2 + 4 + pw*2, QImage::Format_ARGB32_Premultiplied); - roundRect.fill(0); - QPainter p(&roundRect); - p.setRenderHint(QPainter::Antialiasing); - if (d->pen && d->pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); - p.setPen(pn); - } else { - p.setPen(Qt::NoPen); + QString key = QString("QFxRect://r_%1_%2_%3_%4").arg(pw).arg(d->radius).arg((d->pen && d->pen->isValid())?d->pen->color().name():QString()).arg(d->color.name()); + + d->rectTexture = cachedTexture(key); + + if (!d->rectTexture) { + QPixmap roundRect(d->radius*2 + 4 + pw*2, d->radius*2 + 4 + pw*2); + roundRect.fill(Qt::transparent); + QPainter p(&roundRect); + p.setRenderHint(QPainter::Antialiasing); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } + p.setBrush(d->color); + p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->radius, d->radius); + + d->rectTexture = cachedTexture(key, roundRect); } - p.setBrush(d->color); - p.drawRoundedRect((pw+1)/2, (pw+1)/2, roundRect.width()-(pw+1)/2*2, roundRect.height()-(pw+1)/2*2, d->radius, d->radius); - d->rectTexture.setImage(roundRect, GLTexture::PowerOfTwo); } } void QFxRect::generateBorderedRect() { Q_D(QFxRect); - if (d->rectTexture.isNull()) { + if (!d->rectTexture) { const int pw = d->pen && d->pen->isValid() ? d->pen->width() : 0; - QImage borderedRect(pw*2 + 4, pw*2 + 4, QImage::Format_ARGB32_Premultiplied); - borderedRect.fill(0); - QPainter p(&(borderedRect)); - p.setRenderHint(QPainter::Antialiasing); - if (d->pen && d->pen->isValid()) { - QPen pn(QColor(pen()->color()), pen()->width()); - p.setPen(pn); - } else { - p.setPen(Qt::NoPen); + QString key = QString("QFxRect://b_%1_%2_%3_%4").arg(pw).arg(d->radius).arg((d->pen && d->pen->isValid())?d->pen->color().name():QString()).arg(d->color.name()); + + d->rectTexture = cachedTexture(key); + + if (!d->rectTexture) { + QPixmap borderedRect(pw*2 + 4, pw*2 + 4); + borderedRect.fill(Qt::transparent); + QPainter p(&(borderedRect)); + p.setRenderHint(QPainter::Antialiasing); + if (d->pen && d->pen->isValid()) { + QPen pn(QColor(pen()->color()), pen()->width()); + p.setPen(pn); + } else { + p.setPen(Qt::NoPen); + } + p.setBrush(d->color); + p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); + d->rectTexture = cachedTexture(key, borderedRect); } - p.setBrush(d->color); - p.drawRect(qreal(pw+1)/2, qreal(pw+1)/2, borderedRect.width()-(pw+1)/2*2, borderedRect.height()-(pw+1)/2*2); - d->rectTexture.setImage(borderedRect, GLTexture::PowerOfTwo); } } #endif @@ -721,8 +743,8 @@ void QFxRect::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); - float texWidth = d->rectTexture.width(); - float texHeight = d->rectTexture.height(); + float texWidth = d->rectTexture->width(); + float texHeight = d->rectTexture->height(); if (!texWidth || !texHeight) return; @@ -756,10 +778,10 @@ void QFxRect::paintGLContents(GLPainter &p) if (offset==1) texleft=texright=textop=texbottom=0.5; - texleft *= d->rectTexture.glWidth(); - texright *= d->rectTexture.glWidth(); - textop *= d->rectTexture.glHeight(); - texbottom *= d->rectTexture.glHeight(); + texleft *= d->rectTexture->glWidth(); + texright *= d->rectTexture->glWidth(); + textop *= d->rectTexture->glHeight(); + texbottom *= d->rectTexture->glHeight(); float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, @@ -852,35 +874,35 @@ void QFxRect::paintGLContents(GLPainter &p) texright, 0, texright, textop, - d->rectTexture.glWidth(), 0, + d->rectTexture->glWidth(), 0, texright, textop, - d->rectTexture.glWidth(), 0, - d->rectTexture.glWidth(), textop, + d->rectTexture->glWidth(), 0, + d->rectTexture->glWidth(), textop, - 0, d->rectTexture.glHeight(), + 0, d->rectTexture->glHeight(), 0, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), 0, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), texleft, texbottom, - texleft, d->rectTexture.glHeight(), + texleft, d->rectTexture->glHeight(), texleft, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texleft, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texright, texbottom, - texright, d->rectTexture.glHeight(), + texright, d->rectTexture->glHeight(), texright, texbottom, - d->rectTexture.glWidth(), d->rectTexture.glHeight(), + d->rectTexture->glWidth(), d->rectTexture->glHeight(), texright, texbottom, - d->rectTexture.glWidth(), d->rectTexture.glHeight(), - d->rectTexture.glWidth(), texbottom, + d->rectTexture->glWidth(), d->rectTexture->glHeight(), + d->rectTexture->glWidth(), texbottom, 0, textop, 0, texbottom, @@ -900,15 +922,15 @@ void QFxRect::paintGLContents(GLPainter &p) texright, textop, texright, texbottom, - d->rectTexture.glWidth(), textop, + d->rectTexture->glWidth(), textop, texright, texbottom, - d->rectTexture.glWidth(), textop, - d->rectTexture.glWidth(), texbottom }; + d->rectTexture->glWidth(), textop, + d->rectTexture->glWidth(), texbottom }; - glBindTexture(GL_TEXTURE_2D, d->rectTexture.texture()); + glBindTexture(GL_TEXTURE_2D, d->rectTexture->texture()); shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); diff --git a/src/declarative/fx/qfxrect_p.h b/src/declarative/fx/qfxrect_p.h index 6d11917..d68eb4e 100644 --- a/src/declarative/fx/qfxrect_p.h +++ b/src/declarative/fx/qfxrect_p.h @@ -69,7 +69,7 @@ class QFxRectPrivate : public QFxItemPrivate public: QFxRectPrivate() - : gradient(0), pen(0), radius(0) + : rectTexture(0), gradient(0), pen(0), radius(0) { } @@ -83,7 +83,7 @@ public: } #if defined(QFX_RENDER_OPENGL) - GLTexture rectTexture; + QSimpleCanvasItem::CachedTexture *rectTexture; #endif QColor getColor(); QColor color; |