From bc45ef6135b6a01d7fa601765647f2607ee047c8 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 3 Jun 2009 11:56:45 +1000 Subject: OpenGL perf improvements --- src/declarative/canvas/qsimplecanvas.cpp | 3 + src/declarative/canvas/qsimplecanvas_opengl.cpp | 187 +++++++++---- src/declarative/canvas/qsimplecanvasitem.cpp | 4 +- src/declarative/canvas/qsimplecanvasitem.h | 11 +- src/declarative/canvas/qsimplecanvasitem_p.h | 4 +- src/declarative/fx/qfximage.cpp | 348 ++++++++++-------------- src/declarative/fx/qfxrect.cpp | 312 ++++++++------------- src/declarative/fx/qfxtext.cpp | 92 +------ src/declarative/opengl/gltexture.cpp | 65 +++-- src/declarative/opengl/gltexture.h | 5 +- 10 files changed, 473 insertions(+), 558 deletions(-) diff --git a/src/declarative/canvas/qsimplecanvas.cpp b/src/declarative/canvas/qsimplecanvas.cpp index 59edf74..f1ff61b 100644 --- a/src/declarative/canvas/qsimplecanvas.cpp +++ b/src/declarative/canvas/qsimplecanvas.cpp @@ -921,6 +921,9 @@ bool QSimpleCanvas::event(QEvent *e) #if defined(QFX_RENDER_OPENGL1) unsigned int zero = 0; d->root->d_func()->setupPainting(0, rect(), &zero); +#elif defined(QFX_RENDER_OPENGL2) + ++d->paintVersion; + d->root->d_func()->setupPainting(0); #else ++d->paintVersion; d->root->d_func()->setupPainting(0, rect()); diff --git a/src/declarative/canvas/qsimplecanvas_opengl.cpp b/src/declarative/canvas/qsimplecanvas_opengl.cpp index ec809ff..dd57c14 100644 --- a/src/declarative/canvas/qsimplecanvas_opengl.cpp +++ b/src/declarative/canvas/qsimplecanvas_opengl.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE void CanvasEGLWidget::paintGL() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); _canvas->paintGL(); @@ -112,13 +112,16 @@ void QSimpleCanvasPrivate::paintGL() lrpTimer.start(); QSimpleCanvasItemPrivate::GLPaintParameters p; + QSimpleCanvasItem::GLPainter painter; + p.sceneRect = QRect(0, 0, q->width(), q->height()); p.clipRect = p.sceneRect; p.stencilValue = 0; p.opacity = 1; p.forceParamRefresh = false; - if (!isSetup) - root->d_func()->setupPainting(0, QRect()); + p.painter = &painter; + if (!isSetup) + root->d_func()->setupPainting(0); root->d_func()->paint(p); lrpTime = lrpTimer.elapsed(); @@ -195,7 +198,8 @@ void QSimpleCanvasItemPrivate::simplePaintChild(const GLPaintParameters ¶ms, childParams.boundingRect = child->boundingRect(); if (child->filter() && child->filter()->enabled()) { - QSimpleCanvasItem::GLPainter painter(q); + QSimpleCanvasItem::GLPainter &painter = *params.painter; + painter.item = q; painter.activeTransform = child->d_func()->data()->transformActive; painter.activeOpacity = child->d_func()->data()->activeOpacity; painter.sceneClipRect = params.clipRect; @@ -229,34 +233,35 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) QSimpleCanvasItemData *const childData = childPrivate->data(); childData->activeOpacity = myData->activeOpacity; - if (childData->visible != 1) + if (childData->visible != 1.) childData->activeOpacity *= childData->visible; - if (childData->activeOpacity != 0) { + if (childData->activeOpacity != 0.) { + QSimpleCanvas::Matrix &am = childData->transformActive; + am = myData->transformActive; + // Calculate child's transform const qreal x = childData->x; const qreal y = childData->y; const qreal scale = childPrivate->scale; QSimpleCanvasItem::Flip flip = childData->flip; - QSimpleCanvas::Matrix &am = childData->transformActive; - am = myData->transformActive; if (x != 0. || y != 0.) am.translate(x, y); if (scale != 1.) { - QPointF to = childPrivate->transformOrigin(); - bool translate = (to.x() != 0. || to.y() != 0.); - if (translate) + if (childPrivate->origin == QSimpleCanvasItem::TopLeft) { + am.scale(scale, scale); + } else { + QPointF to = childPrivate->transformOrigin(); am.translate(to.x(), to.y()); - am.scale(scale, scale); - if (translate) + am.scale(scale, scale); am.translate(-to.x(), -to.y()); + } } if (childData->transformUser) am *= *childData->transformUser; - if (flip) { QRectF br = child->boundingRect(); am.translate(br.width() / 2., br.height() / 2); @@ -268,8 +273,10 @@ void QSimpleCanvasItemPrivate::setupChildState(QSimpleCanvasItem *child) } } -QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &bounding) +//#define QSIMPLECANVAS_DISABLE_TREE_CLIPPING +QRectF QSimpleCanvasItemPrivate::setupPainting(int version) { + static QRectF scene(-1., -1., 2., 2.); Q_Q(QSimpleCanvasItem); bool hasContents = options & QSimpleCanvasItem::HasContents; @@ -285,17 +292,34 @@ QRectF QSimpleCanvasItemPrivate::setupPainting(int version, const QRect &boundin rv = active.mapRect(filteredBoundRect); } - - for (int ii = 0; ii < children.count(); ++ii) { - QSimpleCanvasItem *child = children.at(ii); - setupChildState(child); - - QSimpleCanvasItemData *childData = child->d_func()->data(); - if (childData->activeOpacity != 0) - rv |= child->d_func()->setupPainting(version, bounding); - } +#ifdef QSIMPLECANVAS_DISABLE_TREE_CLIPPING + myData->doNotPaint = false; + myData->doNotPaintChildren = false; +#else + myData->doNotPaint = !hasContents || !rv.intersects(scene); + myData->doNotPaintChildren = hasContents && myData->doNotPaint && + (clip != QSimpleCanvasItem::NoClip); +#endif + + if (myData->doNotPaintChildren) { + rv = QRectF(); + } else { + for (int ii = 0; ii < children.count(); ++ii) { + QSimpleCanvasItem *child = children.at(ii); + setupChildState(child); + + QSimpleCanvasItemData *childData = child->d_func()->data(); + if (childData->activeOpacity != 0) + rv |= child->d_func()->setupPainting(version); + } + +#ifndef QSIMPLECANVAS_DISABLE_TREE_CLIPPING + myData->doNotPaintChildren |= !rv.intersects(scene); +#endif + } myData->lastPaintRect = rv; + return rv; } @@ -306,6 +330,10 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas Q_Q(QSimpleCanvasItem); + bool doNotPaintChildren = data()->doNotPaintChildren; + if (doNotPaintChildren) + return; + GLPaintParameters params = oldParams; qreal width = params.boundingRect.width(); @@ -327,12 +355,12 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); ConstantColorShader *shader = basicShaders()->constantColor(); + params.painter->invalidate(); shader->enable(); shader->setTransform(data()->transformActive); shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -369,9 +397,11 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas } } - if (layer & QSimpleCanvasFilter::Item && - q->options() & QSimpleCanvasItem::HasContents) { - QSimpleCanvasItem::GLPainter painter(q); + bool doNotPaint = data()->doNotPaint; + + if (!doNotPaint && layer & QSimpleCanvasFilter::Item) { + QSimpleCanvasItem::GLPainter &painter = *params.painter; + painter.item = q; painter.activeTransform = data()->transformActive; painter.activeOpacity = data()->activeOpacity; painter.sceneClipRect = params.clipRect; @@ -390,14 +420,14 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_EQUAL, params.stencilValue + 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); - + + params.painter->invalidate(); ConstantColorShader *shader = basicShaders()->constantColor(); shader->enable(); shader->setTransform(data()->transformActive); shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); glStencilFunc(GL_EQUAL, params.stencilValue, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); @@ -405,43 +435,76 @@ void QSimpleCanvasItemPrivate::paint(GLPaintParameters &oldParams, QSimpleCanvas } } +enum ShaderType { ST_None, ST_SingleTexture, ST_SingleTextureOpacity, ST_Color }; + +QSimpleCanvasItem::GLPainter::GLPainter() +: item(0), activeOpacity(1), flags(0) +{ +} + +QSimpleCanvasItem::GLPainter::GLPainter(QSimpleCanvasItem *i) +: item(i), activeOpacity(1), flags(0) +{ +} + QGLShaderProgram *QSimpleCanvasItem::GLPainter::useTextureShader() { if (activeOpacity == 1.) { - item->basicShaders()->singleTexture()->enable(); - item->basicShaders()->singleTexture()->setTransform(activeTransform); - return item->basicShaders()->singleTexture(); + SingleTextureShader *shader = item->basicShaders()->singleTexture(); + if (flags != ST_SingleTexture) { + shader->enable(); + flags = ST_SingleTexture; + } + + shader->setTransform(activeTransform); + return shader; } else { - item->basicShaders()->singleTextureOpacity()->enable(); - item->basicShaders()->singleTextureOpacity()->setTransform(activeTransform); - item->basicShaders()->singleTextureOpacity()->setOpacity(activeOpacity); - return item->basicShaders()->singleTextureOpacity(); + SingleTextureOpacityShader *shader = item->basicShaders()->singleTextureOpacity(); + + if (flags != ST_SingleTextureOpacity) { + shader->enable(); + flags = ST_SingleTextureOpacity; + } + + shader->setTransform(activeTransform); + shader->setOpacity(activeOpacity); + return shader; } +} +void QSimpleCanvasItem::GLPainter::invalidate() +{ + flags = ST_None; } QGLShaderProgram *QSimpleCanvasItem::GLPainter::useColorShader(const QColor &color) { - QColor c = color; - item->basicShaders()->constantColor()->enable(); - if (activeOpacity != 1.) { - c.setAlpha(int(c.alpha() * activeOpacity)); + QColor c = color; + + ConstantColorShader *shader = item->basicShaders()->constantColor(); + + if (flags != ST_Color) { + shader->enable(); + flags = ST_Color; } - item->basicShaders()->constantColor()->setColor(c); - item->basicShaders()->constantColor()->setTransform(activeTransform); + if (activeOpacity != 1.) + c.setAlpha(int(c.alpha() * activeOpacity)); + + shader->setColor(c); + shader->setTransform(activeTransform); - return item->basicShaders()->constantColor(); + return shader; } -void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point, - const GLTexture &texture) +void QSimpleCanvasItem::GLPainter::drawPixmap(const QPointF &point, + const GLTexture &texture) { drawPixmap(QRectF(point, QSizeF(texture.width(), texture.height())), texture); } -void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, - const GLTexture &img) +void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, + const GLTexture &img) { QGLShaderProgram *shader = useTextureShader(); @@ -466,9 +529,33 @@ void QSimpleCanvasItem::GLPainter::drawPixmap(const QRectF &rect, glBindTexture(GL_TEXTURE_2D, img.texture()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + +void QSimpleCanvasItem::GLPainter::fillRect(const QRectF &rect, + const QColor &color) +{ + if (color.alpha() == 0xFF) + glDisable(GL_BLEND); + + QGLShaderProgram *shader = useColorShader(color); + float x = rect.x(); + float y = rect.y(); + float width = rect.width(); + float height = rect.height(); + + GLfloat vertices[] = { x, height, + width, height, + x, y, + + width, height, + x, y, + width, y }; + + shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); + glDrawArrays(GL_TRIANGLES, 0, 6); - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); + if (color.alpha() == 0xFF) + glEnable(GL_BLEND); } QT_END_NAMESPACE diff --git a/src/declarative/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp index f2222a9..7451a5f 100644 --- a/src/declarative/canvas/qsimplecanvasitem.cpp +++ b/src/declarative/canvas/qsimplecanvasitem.cpp @@ -51,8 +51,8 @@ QT_BEGIN_NAMESPACE QSimpleCanvasItemData::QSimpleCanvasItemData() : buttons(Qt::NoButton), flip(QSimpleCanvasItem::NoFlip), dirty(false), transformValid(true), doNotPaint(false), - doNotPaintChildren(false), x(0), y(0), z(0), visible(1), - transformUser(0), transformVersion(0), activeOpacity(1) + doNotPaintChildren(false), x(0), y(0), z(0), + visible(1), transformUser(0), transformVersion(0), activeOpacity(1) { } diff --git a/src/declarative/canvas/qsimplecanvasitem.h b/src/declarative/canvas/qsimplecanvasitem.h index f817799..68219de 100644 --- a/src/declarative/canvas/qsimplecanvasitem.h +++ b/src/declarative/canvas/qsimplecanvasitem.h @@ -167,7 +167,8 @@ public: class GLPainter { public: - GLPainter(QSimpleCanvasItem *i) : item(i), activeOpacity(1) {} + GLPainter(); + GLPainter(QSimpleCanvasItem *i); QSimpleCanvasItem *item; QSimpleCanvas::Matrix activeTransform; qreal activeOpacity; @@ -175,9 +176,13 @@ public: QGLShaderProgram *useTextureShader(); QGLShaderProgram *useColorShader(const QColor &); - void drawPixmap(const QPointF &, const GLTexture &); - void drawPixmap(const QRectF &, const GLTexture &); + void drawPixmap(const QPointF &, const GLTexture &); + void drawPixmap(const QRectF &, const GLTexture &); + void fillRect(const QRectF &, const QColor &); + + void invalidate(); private: + int flags; GLPainter(const GLPainter &); GLPainter &operator=(const GLPainter &); }; diff --git a/src/declarative/canvas/qsimplecanvasitem_p.h b/src/declarative/canvas/qsimplecanvasitem_p.h index e2deab2..27ee0a2 100644 --- a/src/declarative/canvas/qsimplecanvasitem_p.h +++ b/src/declarative/canvas/qsimplecanvasitem_p.h @@ -218,9 +218,11 @@ public: #endif float opacity; bool forceParamRefresh; + + QSimpleCanvasItem::GLPainter *painter; }; #if defined(QFX_RENDER_OPENGL2) - QRectF setupPainting(int version, const QRect &bounding); + QRectF setupPainting(int version); #elif defined(QFX_RENDER_OPENGL1) QRectF setupPainting(int version, const QRect &bounding, unsigned int *zero); #endif diff --git a/src/declarative/fx/qfximage.cpp b/src/declarative/fx/qfximage.cpp index 22e5d97..1fc84eb 100644 --- a/src/declarative/fx/qfximage.cpp +++ b/src/declarative/fx/qfximage.cpp @@ -448,9 +448,9 @@ uint QFxImage::glSimpleItemData(float *vertices, float *texVertices, texVertices[6] = tileWidth; texVertices[7] = tileHeight; } else { texVertices[0] = 0; texVertices[1] = 0; - texVertices[2] = 1; texVertices[3] = 0; - texVertices[4] = 0; texVertices[5] = 1; - texVertices[6] = 1; texVertices[7] = 1; + 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; @@ -481,25 +481,57 @@ void QFxImage::paintGLContents(GLPainter &p) restoreBlend = true; } + d->checkDirty(); + if (d->_tiled || (!d->_scaleGrid || d->_scaleGrid->isNull())) { - GLfloat vertices[8]; - GLfloat texVertices[8]; - GLTexture *tex = 0; + if (!d->_tiled) { + + float widthV = width(); + float heightV = height(); + float glWidth = d->_tex.glWidth(); + float glHeight = d->_tex.glHeight(); + + float vert[] = { + 0, heightV, + widthV, heightV, + 0, 0, - QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + widthV, heightV, + 0, 0, + widthV, 0 }; - shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); + float tex[] = { + 0, 0, + glWidth, 0, + 0, glHeight, + + glWidth, 0, + 0, glHeight, + glWidth, glHeight + }; + + shader->setAttributeArray(SingleTextureShader::Vertices, vert, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex, 2); + glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); + glDrawArrays(GL_TRIANGLES, 0, 6); + + } else { - glBindTexture(GL_TEXTURE_2D, tex->texture()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + GLfloat vertices[8]; + GLfloat texVertices[8]; + GLTexture *tex = 0; - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); + QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + + shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); + + glBindTexture(GL_TEXTURE_2D, tex->texture()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } } else { - d->checkDirty(); float imgWidth = d->_pix.width(); float imgHeight = d->_pix.height(); @@ -546,235 +578,155 @@ void QFxImage::paintGLContents(GLPainter &p) float vert1[] = { 0, 0, 0, imgtop, imgleft, 0, + + 0, imgtop, + imgleft, 0, + imgleft, imgtop, + + imgleft, 0, imgleft, imgtop, imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, - 0, textop, - texleft, 1, - texleft, textop, - texright, 1, - texright, textop, - 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, + imgleft, imgtop, - imgleft, imgbottom, + imgright, 0, imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, - 0, texbottom, - texleft, textop, - texleft, texbottom, - texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, - 0, 0, - texleft, texbottom, - texleft, 0, - texright, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; - - glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); - shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); - } + imgright, 0, + imgright, imgtop, + widthV, 0, - if (restoreBlend) - glEnable(GL_BLEND); -} -#elif defined(QFX_RENDER_OPENGL1) -void QFxImage::paintGLContents(GLPainter &p) -{ - Q_D(QFxImage); - if (d->_pix.isNull()) - return; + imgright, imgtop, + widthV, 0, + widthV, imgtop, - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); + 0, imgtop, + 0, imgbottom, + imgleft, imgtop, - bool restoreBlend = false; - if (isOpaque() && p.activeOpacity == 1) { - glDisable(GL_BLEND); - restoreBlend = true; - } + 0, imgbottom, + imgleft, imgtop, + imgleft, imgbottom, - glEnable(GL_TEXTURE_2D); - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } + imgleft, imgtop, + imgleft, imgbottom, + imgright, imgtop, - if (d->_tiled || !d->_scaleGrid || d->_scaleGrid->isNull()) { + imgleft, imgbottom, + imgright, imgtop, + imgright, imgbottom, - GLfloat vertices[8]; - GLfloat texVertices[8]; - GLTexture *tex = 0; + imgright, imgtop, + imgright, imgbottom, + widthV, imgtop, - QFxImage::glSimpleItemData(vertices, texVertices, &tex, 8); + imgright, imgbottom, + widthV, imgtop, + widthV, imgbottom, - glBindTexture(GL_TEXTURE_2D, tex->texture()); + 0, imgbottom, + 0, heightV, + imgleft, imgbottom, - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + 0, heightV, + imgleft, imgbottom, + imgleft, heightV, - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texVertices); + imgleft, imgbottom, + imgleft, heightV, + imgright, imgbottom, + imgleft, heightV, + imgright, imgbottom, + imgright, heightV, - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + imgright, imgbottom, + imgright, heightV, + widthV, imgbottom, - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + imgright, heightV, + widthV, imgbottom, + widthV, heightV }; - } else { - d->checkDirty(); + float tex1[] = { 0, 1, + 0, textop, + texleft, 1, - float imgWidth = d->_pix.width(); - float imgHeight = d->_pix.height(); - if (!imgWidth || !imgHeight) { - if (restoreBlend) - glEnable(GL_BLEND); - return; - } + 0, textop, + texleft, 1, + texleft, textop, - float widthV = width(); - float heightV = height(); + texleft, 1, + texleft, textop, + texright, 1, - float texleft = 0; - float texright = 1; - float textop = 1; - float texbottom = 0; - float imgleft = 0; - float imgright = widthV; - float imgtop = 0; - float imgbottom = heightV; + texleft, textop, + texright, 1, + texright, textop, - const int sgl = d->_scaleGrid->left(); - const int sgr = d->_scaleGrid->right(); - const int sgt = d->_scaleGrid->top(); - const int sgb = d->_scaleGrid->bottom(); + texright, 1, + texright, textop, + 1, 1, - if (sgl) { - texleft = float(sgl) / imgWidth; - imgleft = sgl; - } - if (sgr) { - texright = 1. - float(sgr) / imgWidth; - imgright = widthV - sgr; - } - if (sgt) { - textop = 1. - float(sgb) / imgHeight; - imgtop = sgt; - } - if (sgb) { - texbottom = float(sgt) / imgHeight; - imgbottom = heightV - sgb; - } + texright, textop, + 1, 1, + 1, textop, - float vert1[] = { 0, 0, - 0, imgtop, - imgleft, 0, - imgleft, imgtop, - imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, 0, textop, - texleft, 1, + 0, texbottom, texleft, textop, - texright, 1, - texright, textop, - 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, - imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, + 0, texbottom, texleft, textop, texleft, texbottom, + + texleft, textop, + texleft, texbottom, + texright, textop, + + texleft, texbottom, + texright, textop, + texright, texbottom, + texright, textop, texright, texbottom, 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, + + texright, texbottom, + 1, textop, + 1, texbottom, + + 0, texbottom, + 0, 0, + texleft, texbottom, + 0, 0, texleft, texbottom, texleft, 0, + + texleft, texbottom, + texleft, 0, + texright, texbottom, + + texleft, 0, + texright, texbottom, + texright, 0, + texright, texbottom, texright, 0, 1, texbottom, + + texright, 0, + 1, texbottom, 1, 0 }; glBindTexture(GL_TEXTURE_2D, d->_tex.texture()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vert1); - glTexCoordPointer(2, GL_FLOAT, 0, tex1); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert2); - glTexCoordPointer(2, GL_FLOAT, 0, tex2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert3); - glTexCoordPointer(2, GL_FLOAT, 0, tex3); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); + glDrawArrays(GL_TRIANGLES, 0, 54); } - if (restoreBlend) + if (restoreBlend) glEnable(GL_BLEND); } #endif diff --git a/src/declarative/fx/qfxrect.cpp b/src/declarative/fx/qfxrect.cpp index c156753..3d6897e 100644 --- a/src/declarative/fx/qfxrect.cpp +++ b/src/declarative/fx/qfxrect.cpp @@ -692,6 +692,7 @@ void QFxRect::paintGLContents(GLPainter &p) colors[i+3] = c.alphaF() * p.activeOpacity; colors[i+7] = colors[i+3]; } + p.invalidate(); ColorShader *shader = basicShaders()->color(); shader->enable(); shader->setTransform(p.activeTransform); @@ -702,19 +703,9 @@ void QFxRect::paintGLContents(GLPainter &p) shader->disableAttributeArray(ColorShader::Vertices); shader->disableAttributeArray(ColorShader::Colors); } else { - QGLShaderProgram *shader = p.useColorShader(d->getColor()); - float widthV = width(); - float heightV = height(); - - GLfloat vertices[] = { 0, heightV, - widthV, heightV, - 0, 0, - widthV, 0 }; + p.fillRect(QRectF(0, 0, width(), height()), d->getColor()); - shader->setAttributeArray(ConstantColorShader::Vertices, vertices, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - shader->disableAttributeArray(ConstantColorShader::Vertices); } } else { qreal offset = 0; @@ -768,236 +759,155 @@ void QFxRect::paintGLContents(GLPainter &p) float vert1[] = { -pw/2, -pw/2, -pw/2, imgtop, imgleft, -pw/2, + + -pw/2, imgtop, + imgleft, -pw/2, + imgleft, imgtop, + + imgleft, -pw/2, + imgleft, imgtop, + imgright, -pw/2, + imgleft, imgtop, imgright, -pw/2, imgright, imgtop, + + imgright, -pw/2, + imgright, imgtop, widthV, -pw/2, - widthV, imgtop }; - float tex1[] = { 0, 0, - 0, textop, - texleft, 0, - texleft, textop, - texright, 0, - texright, textop, - 1, 0, - 1, textop }; - float vert2[] = { -pw/2, imgtop, - -pw/2, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, + imgright, imgtop, - imgright, imgbottom, + widthV, -pw/2, widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, - 0, texbottom, - texleft, textop, - texleft, texbottom, - texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { -pw/2, heightV, + + -pw/2, heightV, -pw/2, imgbottom, imgleft, heightV, + + -pw/2, imgbottom, + imgleft, heightV, + imgleft, imgbottom, + + imgleft, heightV, imgleft, imgbottom, imgright, heightV, + + imgleft, imgbottom, + imgright, heightV, + imgright, imgbottom, + + imgright, heightV, imgright, imgbottom, widthV, heightV, - widthV, imgbottom }; - float tex3[] = { 0, 1, - 0, texbottom, - texleft, 1, - texleft, texbottom, - texright, 1, - texright, texbottom, - 1, 1, - 1, texbottom }; - glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); + imgright, imgbottom, + widthV, heightV, + widthV, imgbottom, - shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - if (yMiddles) { - shader->setAttributeArray(SingleTextureShader::Vertices, vert2, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex2, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - } - shader->setAttributeArray(SingleTextureShader::Vertices, vert3, 2); - shader->setAttributeArray(SingleTextureShader::TextureCoords, tex3, 2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + -pw/2, imgtop, + -pw/2, imgbottom, + imgleft, imgtop, - shader->disableAttributeArray(SingleTextureShader::Vertices); - shader->disableAttributeArray(SingleTextureShader::TextureCoords); - } -} -#elif defined(QFX_RENDER_OPENGL1) -void QFxRect::paintGLContents(GLPainter &p) -{ - Q_D(QFxRect); + -pw/2, imgbottom, + imgleft, imgtop, + imgleft, imgbottom, - float widthV = width(); - float heightV = height(); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); - - if (d->_radius == 0 && (!d->_pen || !d->_pen->isValid())) { - GLfloat vertices[] = { 0, heightV, - widthV, heightV, - 0, 0, - widthV, 0 }; + imgleft, imgtop, + imgleft, imgbottom, + imgright, imgtop, - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2,GL_FLOAT,0,vertices); + imgleft, imgbottom, + imgright, imgtop, + imgright, imgbottom, - QColor c; - if (d->_gradcolor.isValid()) - c = d->_color; - else - c = d->getColor(); - float r = c.redF(); - float g = c.greenF(); - float b = c.blueF(); - float a = c.alphaF() * p.activeOpacity; - - float r2 = r; float g2 = g; float b2 = b; float a2 = a; - - if (d->_gradcolor.isValid()) { - r2 = d->_gradcolor.redF(); - g2 = d->_gradcolor.greenF(); - b2 = d->_gradcolor.blueF(); - a2 = d->_gradcolor.alphaF() * p.activeOpacity; - } + imgright, imgtop, + imgright, imgbottom, + widthV, imgtop, + + imgright, imgbottom, + widthV, imgtop, + widthV, imgbottom }; - GLfloat colors[] = { r2, g2, b2, a2, - r2, g2, b2, a2, - r, g, b, a, - r, g, b, a }; - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4,GL_FLOAT,0,colors); + float tex1[] = { 0, 0, + 0, textop, + texleft, 0, - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + 0, textop, + texleft, 0, + texleft, textop, - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } else { - qreal offset = 0; - if (d->_radius > 0) { - generateRoundedRect(); - offset = d->_radius; - } else { - generateBorderedRect(); - offset = d->pen()->width(); - } + texleft, 0, + texleft, textop, + texright, 0, - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } + texleft, textop, + texright, 0, + texright, textop, - float texWidth = d->_rectTexture.width(); - float texHeight = d->_rectTexture.height(); - if (!texWidth || !texHeight) - return; + texright, 0, + texright, textop, + 1, 0, - float widthV = width(); - float heightV = height(); - - float texleft = 0; - float texright = 1; - float textop = 1; - float texbottom = 0; - float imgleft = 0; - float imgright = widthV; - float imgtop = 0; - float imgbottom = heightV; - - texleft = float(offset) / texWidth; - imgleft = offset; - texright = 1. - float(offset) / texWidth; - imgright = widthV - offset; - textop = 1. - float(offset) / texHeight; - imgtop = offset; - texbottom = float(offset) / texHeight; - imgbottom = heightV - offset; - - float vert1[] = { 0, 0, - 0, imgtop, - imgleft, 0, - imgleft, imgtop, - imgright, 0, - imgright, imgtop, - widthV, 0, - widthV, imgtop }; - float tex1[] = { 0, 1, - 0, textop, + texright, textop, + 1, 0, + 1, textop, + + 0, 1, + 0, texbottom, texleft, 1, - texleft, textop, + + 0, texbottom, + texleft, 1, + texleft, texbottom, + + texleft, 1, + texleft, texbottom, texright, 1, - texright, textop, + + texleft, texbottom, + texright, 1, + texright, texbottom, + + texright, 1, + texright, texbottom, 1, 1, - 1, textop }; - float vert2[] = { 0, imgtop, - 0, imgbottom, - imgleft, imgtop, - imgleft, imgbottom, - imgright, imgtop, - imgright, imgbottom, - widthV, imgtop, - widthV, imgbottom }; - float tex2[] = { 0, textop, + + texright, texbottom, + 1, 1, + 1, texbottom, + + 0, textop, 0, texbottom, texleft, textop, + + 0, texbottom, + texleft, textop, + texleft, texbottom, + + texleft, textop, texleft, texbottom, texright, textop, - texright, texbottom, - 1, textop, - 1, texbottom }; - float vert3[] = { 0, imgbottom, - 0, heightV, - imgleft, imgbottom, - imgleft, heightV, - imgright, imgbottom, - imgright, heightV, - widthV, imgbottom, - widthV, heightV }; - float tex3[] = { 0, texbottom, - 0, 0, + texleft, texbottom, - texleft, 0, + texright, textop, texright, texbottom, - texright, 0, - 1, texbottom, - 1, 0 }; - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); + texright, textop, + texright, texbottom, + 1, textop, - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + texright, texbottom, + 1, textop, + 1, texbottom }; - glVertexPointer(2, GL_FLOAT, 0, vert1); - glTexCoordPointer(2, GL_FLOAT, 0, tex1); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert2); - glTexCoordPointer(2, GL_FLOAT, 0, tex2); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); - glVertexPointer(2, GL_FLOAT, 0, vert3); - glTexCoordPointer(2, GL_FLOAT, 0, tex3); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + glBindTexture(GL_TEXTURE_2D, d->_rectTexture.texture()); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); + shader->setAttributeArray(SingleTextureShader::Vertices, vert1, 2); + shader->setAttributeArray(SingleTextureShader::TextureCoords, tex1, 2); + glDrawArrays(GL_TRIANGLES, 0, 36 + (yMiddles?18:0)); } } #endif diff --git a/src/declarative/fx/qfxtext.cpp b/src/declarative/fx/qfxtext.cpp index 702ec81..1b5c080 100644 --- a/src/declarative/fx/qfxtext.cpp +++ b/src/declarative/fx/qfxtext.cpp @@ -796,103 +796,31 @@ void QFxText::paintGLContents(GLPainter &p) QGLShaderProgram *shader = p.useTextureShader(); GLfloat vertices[] = { x, y + heightV, - x + widthV, y + heightV, - x, y, - x + widthV, y }; + x + widthV, y + heightV, + x, y, + + x + widthV, y + heightV, + x, y, + x + widthV, y }; GLfloat texVertices[] = { 0, 0, 1, 0, 0, 1, + + 1, 0, + 0, 1, 1, 1 }; shader->setAttributeArray(SingleTextureShader::Vertices, vertices, 2); shader->setAttributeArray(SingleTextureShader::TextureCoords, texVertices, 2); glBindTexture(GL_TEXTURE_2D, d->tex.texture()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDrawArrays(GL_TRIANGLES, 0, 6); shader->disableAttributeArray(SingleTextureShader::Vertices); shader->disableAttributeArray(SingleTextureShader::TextureCoords); } -#elif defined(QFX_RENDER_OPENGL) -void QFxText::paintGLContents(GLPainter &p) -{ - Q_D(QFxText); - d->checkImgCache(); - if (d->imgCache.isNull()) - return; - - int w = width(); - int h = height(); - - float x = 0; - float y = 0; - - switch (d->hAlign) { - case AlignLeft: - x = 0; - break; - case AlignRight: - x = w - d->imgCache.width(); - break; - case AlignHCenter: - x = (w - d->imgCache.width()) / 2; - break; - } - - switch (d->vAlign) { - case AlignTop: - y = 0; - break; - case AlignBottom: - y = h - d->imgCache.height(); - break; - case AlignVCenter: - y = (h - d->imgCache.height()) / 2; - break; - } - - float widthV = d->imgCache.width(); - float heightV = d->imgCache.height(); - - GLfloat vertices[] = { x, y + heightV, - x + widthV, y + heightV, - x, y, - x + widthV, y }; - - GLfloat texVertices[] = { 0, 0, - 1, 0, - 0, 1, - 1, 1 }; - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(p.activeTransform.data()); - glEnable(GL_TEXTURE_2D); - if (p.activeOpacity == 1.) { - GLint i = GL_REPLACE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - } else { - GLint i = GL_MODULATE; - glTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &i); - glColor4f(1, 1, 1, p.activeOpacity); - } - - glBindTexture(GL_TEXTURE_2D, d->tex.texture()); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - glVertexPointer(2, GL_FLOAT, 0, vertices); - glTexCoordPointer(2, GL_FLOAT, 0, texVertices); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_TEXTURE_2D); -} - #endif void QFxText::componentComplete() diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp index 199b362..bebee08 100644 --- a/src/declarative/opengl/gltexture.cpp +++ b/src/declarative/opengl/gltexture.cpp @@ -79,7 +79,8 @@ public: GLTexturePrivate(GLTexture *_q) : q(_q), texture(0), width(0), height(0), horizWrap(GLTexture::Repeat), vertWrap(GLTexture::Repeat), - minFilter(GLTexture::Linear), magFilter(GLTexture::Linear) + minFilter(GLTexture::Linear), magFilter(GLTexture::Linear), + glWidth(1.), glHeight(1.) { } @@ -92,6 +93,9 @@ public: GLTexture::FilterMode minFilter; GLTexture::FilterMode magFilter; + qreal glWidth; + qreal glHeight; + void genTexture(); }; @@ -167,32 +171,43 @@ static inline int npot(int size) by explicitly setting the size, or by previously setting an image), it will be destroyed and a new texture created with \a img's contents and size. */ -void GLTexture::setImage(const QImage &img) +void GLTexture::setImage(const QImage &img, ImageMode mode) { if (img.isNull()) return; d->genTexture(); - //QImage dataImage = img.scaled(npot(img.width()), npot(img.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - QImage dataImage = QGLWidget_convertToGLFormat(img); - glBindTexture(GL_TEXTURE_2D, d->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), - dataImage.height(), 0, - (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, - GL_UNSIGNED_BYTE, dataImage.bits()); - d->width = dataImage.width(); - d->height = dataImage.height(); - -#if 0 - glGenerateMipmap(GL_TEXTURE_2D); - int e = glGetError(); - if (d->magFilter == Linear) - setMagFilter(MipmapLinear); - if (d->minFilter == Linear) - setMinFilter((GLTexture::FilterMode)GL_LINEAR_MIPMAP_LINEAR); -#endif + + // ### Need to respect mode + if (img.format() == QImage::Format_RGB16) { + QImage dataImage = img.mirrored(); + int max = (img.width() > img.height())?img.width():img.height(); + max = npot(max); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, max, + max, 0, + GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, 0); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dataImage.width(), + dataImage.height(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + dataImage.bits()); + + d->glWidth = qreal(dataImage.width()) / qreal(max); + d->glHeight = qreal(dataImage.height()) / qreal(max); + } else { + QImage dataImage = QGLWidget_convertToGLFormat(img); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), + dataImage.height(), 0, + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, dataImage.bits()); + } + + d->width = img.width(); + d->height = img.height(); } void GLTexture::copyImage(const QImage &img, const QPoint &point, @@ -219,6 +234,16 @@ int GLTexture::height() const return d->height; } +qreal GLTexture::glWidth() const +{ + return d->glWidth; +} + +qreal GLTexture::glHeight() const +{ + return d->glHeight; +} + /*! Sets the \a size of the texture. This will destroy the current contents of the texture. If an image has been assigned, it will need to be reassigned diff --git a/src/declarative/opengl/gltexture.h b/src/declarative/opengl/gltexture.h index 787c9a5..d301d8a 100644 --- a/src/declarative/opengl/gltexture.h +++ b/src/declarative/opengl/gltexture.h @@ -69,11 +69,14 @@ public: bool isNull() const; void clear(); - void setImage(const QImage &); + enum ImageMode { NonPowerOfTwo, PowerOfTwo }; + void setImage(const QImage &, ImageMode = NonPowerOfTwo); void copyImage(const QImage &, const QPoint & = QPoint(0, 0), const QRect & = QRect()); int width() const; int height() const; + qreal glWidth() const; + qreal glHeight() const; QSize size() const; void setSize(const QSize &); -- cgit v0.12