summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-06-04 03:35:15 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-06-04 03:35:15 (GMT)
commita276e872e83e0c2f04a367299580ef787b6efc51 (patch)
tree3bb71c20fb6d18c180b6c07fa8bc0326a68acb23 /src/declarative
parentf7cf2cdc0b6c83a639d155987f871f7932c1d845 (diff)
downloadQt-a276e872e83e0c2f04a367299580ef787b6efc51.zip
Qt-a276e872e83e0c2f04a367299580ef787b6efc51.tar.gz
Qt-a276e872e83e0c2f04a367299580ef787b6efc51.tar.bz2
Share GL textures where possible
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/canvas/qsimplecanvas_opengl.cpp84
-rw-r--r--src/declarative/canvas/qsimplecanvas_p.h3
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.h23
-rw-r--r--src/declarative/fx/qfximage.cpp57
-rw-r--r--src/declarative/fx/qfximage_p.h4
-rw-r--r--src/declarative/fx/qfxrect.cpp126
-rw-r--r--src/declarative/fx/qfxrect_p.h4
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;