- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 65 65 // #define QT_OPENGL_CACHE_AS_VBOS 66 66 67 #include "qglgradientcache_p.h" 67 68 #include "qpaintengineex_opengl2_p.h" 68 69 … … 78 79 #include <private/qpixmapdata_gl_p.h> 79 80 #include <private/qdatabuffer_p.h> 80 81 #include "qglgradientcache_p.h" 81 #include <private/qstatictext_p.h> 82 #include <private/qtriangulator_p.h> 83 82 84 #include "qglengineshadermanager_p.h" 83 85 #include "qgl2pexvertexarray_p.h" … … 89 91 QT_BEGIN_NAMESPACE 90 92 91 //#define QT_GL_NO_SCISSOR_TEST 93 #if defined(Q_OS_SYMBIAN) 94 #define QT_GL_NO_SCISSOR_TEST 95 #endif 96 92 97 #if defined(Q_WS_WIN) 93 98 extern Q_GUI_EXPORT bool qt_cleartype_enabled; 94 99 #endif 95 100 96 extern QImage qt_imageForBrush(int brushStyle, bool invert); 101 #ifdef Q_WS_MAC 102 extern bool qt_applefontsmoothing_enabled; 103 #endif 104 105 Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); 97 106 98 107 ////////////////////////////////// Private Methods ////////////////////////////////////////// … … 107 116 e->data = 0; 108 117 e->engine = 0; 118 } 119 120 if (elementIndicesVBOId != 0) { 121 glDeleteBuffers(1, &elementIndicesVBOId); 122 elementIndicesVBOId = 0; 109 123 } 110 124 } … … 150 164 151 165 currentBrush = brush; 166 if (!currentBrushPixmap.isNull()) 167 currentBrushPixmap = QPixmap(); 152 168 brushUniformsDirty = true; // All brushes have at least one uniform 153 169 … … 208 224 } 209 225 else if (style == Qt::TexturePattern) { 210 const QPixmap& texPixmap = currentBrush.texture(); 226 currentBrushPixmap = currentBrush.texture(); 227 228 int max_texture_size = ctx->d_func()->maxTextureSize(); 229 if (currentBrushPixmap.width() > max_texture_size || currentBrushPixmap.height() > max_texture_size) 230 currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); 211 231 212 232 glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); 213 QGLTexture *tex = ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); 233 QGLTexture *tex = ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA, 234 QGLContext::InternalBindOption | 235 QGLContext::CanFlipNativePixmapBindOption); 214 236 updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); 215 237 textureInvertedY = tex->options & QGLContext::InvertedYBindOption ? -1 : 1; … … 366 388 dy = ceilf(dy - 0.5f); 367 389 } 368 390 #ifndef Q_OS_SYMBIAN 369 391 if (addOffset) { 370 392 dx += 0.49f; 371 393 dy += 0.49f; 372 394 } 373 395 #endif 374 396 pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); 375 397 pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); … … 389 411 390 412 matrixDirty = false; 413 matrixUniformDirty = true; 391 414 392 415 // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only … … 507 530 d->transferMode(BrushDrawingMode); 508 531 532 d->nativePaintingActive = true; 533 509 534 QGLContext *ctx = d->ctx; 510 535 glUseProgram(0); … … 522 547 float mv_matrix[4][4] = 523 548 { 524 { mtx.m11(), mtx.m12(), 0, mtx.m13() },525 { mtx.m21(), mtx.m22(), 0, mtx.m23() },526 { 0, 0, 1,0 },527 { mtx.dx(), mtx.dy(), 0, mtx.m33() }549 { float(mtx.m11()), float(mtx.m12()), 0, float(mtx.m13()) }, 550 { float(mtx.m21()), float(mtx.m22()), 0, float(mtx.m23()) }, 551 { 0, 0, 1, 0 }, 552 { float(mtx.dx()), float(mtx.dy()), 0, float(mtx.m33()) } 528 553 }; 529 554 … … 562 587 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 563 588 glStencilFunc(GL_ALWAYS, 0, 0xff); 564 glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);565 glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);566 glDisableVertexAttribArray(QT_OPACITY_ATTR);589 ctx->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false); 590 ctx->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false); 591 ctx->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); 567 592 #ifndef QT_OPENGL_ES_2 568 593 glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib() … … 574 599 Q_D(QGL2PaintEngineEx); 575 600 d->needsSync = true; 601 d->nativePaintingActive = false; 602 } 603 604 void QGL2PaintEngineEx::invalidateState() 605 { 606 Q_D(QGL2PaintEngineEx); 607 d->needsSync = true; 608 } 609 610 bool QGL2PaintEngineEx::isNativePaintingActive() const { 611 Q_D(const QGL2PaintEngineEx); 612 return d->nativePaintingActive; 576 613 } 577 614 … … 586 623 587 624 if (newMode == TextDrawingMode) { 588 setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); 589 setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); 625 shaderManager->setHasComplexGeometry(true); 626 } else { 627 shaderManager->setHasComplexGeometry(false); 590 628 } 591 629 … … 612 650 #ifdef QT_OPENGL_CACHE_AS_VBOS 613 651 GLuint vbo; 652 GLuint ibo; 614 653 #else 615 654 float *vertices; 655 void *indices; 616 656 #endif 617 657 int vertexCount; 658 int indexCount; 618 659 GLenum primitiveType; 619 660 qreal iscale; … … 626 667 Q_ASSERT(engine->type() == QPaintEngine::OpenGL2); 627 668 static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo; 669 if (c->ibo) 670 d->unusedIBOSToClean << c->ibo; 628 671 #else 629 672 Q_UNUSED(engine); 630 673 qFree(c->vertices); 674 qFree(c->indices); 631 675 #endif 632 676 delete c; … … 669 713 QVectorPath::CacheEntry *data = path.lookupCacheData(q); 670 714 QGL2PEVectorPathCache *cache; 715 716 bool updateCache = false; 671 717 672 718 if (data) { … … 679 725 glDeleteBuffers(1, &cache->vbo); 680 726 cache->vbo = 0; 727 Q_ASSERT(cache->ibo == 0); 681 728 #else 682 729 qFree(cache->vertices); 683 #endif 684 cache->vertexCount = 0; 730 Q_ASSERT(cache->indices == 0); 731 #endif 732 updateCache = true; 685 733 } 686 734 } 687 735 } else { 688 736 cache = new QGL2PEVectorPathCache; 689 cache->vertexCount = 0;690 737 data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); 738 updateCache = true; 691 739 } 692 740 693 741 // Flatten the path at the current scale factor and fill it into the cache struct. 694 if ( !cache->vertexCount) {742 if (updateCache) { 695 743 vertexCoordinateArray.clear(); 696 744 vertexCoordinateArray.addPath(path, inverseScale, false); … … 698 746 int floatSizeInBytes = vertexCount * 2 * sizeof(float); 699 747 cache->vertexCount = vertexCount; 748 cache->indexCount = 0; 700 749 cache->primitiveType = GL_TRIANGLE_FAN; 701 750 cache->iscale = inverseScale; … … 704 753 glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); 705 754 glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW); 755 cache->ibo = 0; 706 756 #else 707 757 cache->vertices = (float *) qMalloc(floatSizeInBytes); 708 758 memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes); 759 cache->indices = 0; 709 760 #endif 710 761 } … … 722 773 // printf(" - Marking path as cachable...\n"); 723 774 // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable 724 // ### Remove before release... 725 static bool do_vectorpath_cache = qgetenv("QT_OPENGL_NO_PATH_CACHE").isEmpty(); 726 if (do_vectorpath_cache) 727 path.makeCacheable(); 775 path.makeCacheable(); 728 776 vertexCoordinateArray.clear(); 729 777 vertexCoordinateArray.addPath(path, inverseScale, false); … … 733 781 734 782 } else { 735 // The path is too complicated & needs the stencil technique 736 vertexCoordinateArray.clear(); 737 vertexCoordinateArray.addPath(path, inverseScale, false); 738 739 fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); 740 741 glStencilMask(0xff); 742 glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); 743 744 if (q->state()->clipTestEnabled) { 745 // Pass when high bit is set, replace stencil value with current clip 746 glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT); 747 } else if (path.hasWindingFill()) { 748 // Pass when any bit is set, replace stencil value with 0 749 glStencilFunc(GL_NOTEQUAL, 0, 0xff); 783 bool useCache = path.isCacheable(); 784 if (useCache) { 785 QRectF bbox = path.controlPointRect(); 786 // If the path doesn't fit within these limits, it is possible that the triangulation will fail. 787 useCache &= (bbox.left() > -0x8000 * inverseScale) 788 && (bbox.right() < 0x8000 * inverseScale) 789 && (bbox.top() > -0x8000 * inverseScale) 790 && (bbox.bottom() < 0x8000 * inverseScale); 791 } 792 793 if (useCache) { 794 QVectorPath::CacheEntry *data = path.lookupCacheData(q); 795 QGL2PEVectorPathCache *cache; 796 797 bool updateCache = false; 798 799 if (data) { 800 cache = (QGL2PEVectorPathCache *) data->data; 801 // Check if scale factor is exceeded for curved paths and generate curves if so... 802 if (path.isCurved()) { 803 qreal scaleFactor = cache->iscale / inverseScale; 804 if (scaleFactor < 0.5 || scaleFactor > 2.0) { 805 #ifdef QT_OPENGL_CACHE_AS_VBOS 806 glDeleteBuffers(1, &cache->vbo); 807 glDeleteBuffers(1, &cache->ibo); 808 #else 809 qFree(cache->vertices); 810 qFree(cache->indices); 811 #endif 812 updateCache = true; 813 } 814 } 815 } else { 816 cache = new QGL2PEVectorPathCache; 817 data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); 818 updateCache = true; 819 } 820 821 // Flatten the path at the current scale factor and fill it into the cache struct. 822 if (updateCache) { 823 QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale)); 824 cache->vertexCount = polys.vertices.size() / 2; 825 cache->indexCount = polys.indices.size(); 826 cache->primitiveType = GL_TRIANGLES; 827 cache->iscale = inverseScale; 828 #ifdef QT_OPENGL_CACHE_AS_VBOS 829 glGenBuffers(1, &cache->vbo); 830 glGenBuffers(1, &cache->ibo); 831 glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); 832 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); 833 834 if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) 835 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); 836 else 837 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint16) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); 838 839 QVarLengthArray<float> vertices(polys.vertices.size()); 840 for (int i = 0; i < polys.vertices.size(); ++i) 841 vertices[i] = float(inverseScale * polys.vertices.at(i)); 842 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); 843 #else 844 cache->vertices = (float *) qMalloc(sizeof(float) * polys.vertices.size()); 845 if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) { 846 cache->indices = (quint32 *) qMalloc(sizeof(quint32) * polys.indices.size()); 847 memcpy(cache->indices, polys.indices.data(), sizeof(quint32) * polys.indices.size()); 848 } else { 849 cache->indices = (quint16 *) qMalloc(sizeof(quint16) * polys.indices.size()); 850 memcpy(cache->indices, polys.indices.data(), sizeof(quint16) * polys.indices.size()); 851 } 852 for (int i = 0; i < polys.vertices.size(); ++i) 853 cache->vertices[i] = float(inverseScale * polys.vertices.at(i)); 854 #endif 855 } 856 857 prepareForDraw(currentBrush.isOpaque()); 858 #ifdef QT_OPENGL_CACHE_AS_VBOS 859 glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); 860 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); 861 setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); 862 if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) 863 glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0); 864 else 865 glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0); 866 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 867 glBindBuffer(GL_ARRAY_BUFFER, 0); 868 #else 869 setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices); 870 if (QGLExtensions::glExtensions() & QGLExtensions::ElementIndexUint) 871 glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, (qint32 *)cache->indices); 872 else 873 glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, (qint16 *)cache->indices); 874 #endif 875 750 876 } else { 751 // Pass when high bit is set, replace stencil value with 0 752 glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); 753 } 754 prepareForDraw(currentBrush.isOpaque()); 755 756 // Stencil the brush onto the dest buffer 757 composite(vertexCoordinateArray.boundingRect()); 758 glStencilMask(0); 759 updateClipScissorTest(); 877 // printf(" - Marking path as cachable...\n"); 878 // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable 879 path.makeCacheable(); 880 881 // The path is too complicated & needs the stencil technique 882 vertexCoordinateArray.clear(); 883 vertexCoordinateArray.addPath(path, inverseScale, false); 884 885 fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); 886 887 glStencilMask(0xff); 888 glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); 889 890 if (q->state()->clipTestEnabled) { 891 // Pass when high bit is set, replace stencil value with current clip 892 glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT); 893 } else if (path.hasWindingFill()) { 894 // Pass when any bit is set, replace stencil value with 0 895 glStencilFunc(GL_NOTEQUAL, 0, 0xff); 896 } else { 897 // Pass when high bit is set, replace stencil value with 0 898 glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); 899 } 900 prepareForDraw(currentBrush.isOpaque()); 901 902 // Stencil the brush onto the dest buffer 903 composite(vertexCoordinateArray.boundingRect()); 904 glStencilMask(0); 905 updateClipScissorTest(); 906 } 760 907 } 761 908 } … … 939 1086 brushUniformsDirty = true; 940 1087 opacityUniformDirty = true; 1088 matrixUniformDirty = true; 941 1089 } 942 1090 … … 947 1095 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); 948 1096 opacityUniformDirty = false; 1097 } 1098 1099 if (matrixUniformDirty && shaderManager->hasComplexGeometry()) { 1100 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Matrix), 1101 pmvMatrix); 1102 matrixUniformDirty = false; 949 1103 } 950 1104 … … 1001 1155 } 1002 1156 1003 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp1157 extern Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp 1004 1158 1005 1159 … … 1049 1203 updateMatrix(); 1050 1204 1205 QRectF clip = q->state()->matrix.inverted().mapRect(q->state()->clipEnabled 1206 ? q->state()->rectangleClip 1207 : QRectF(0, 0, width, height)); 1208 1051 1209 if (penStyle == Qt::SolidLine) { 1052 stroker.process(path, pen );1210 stroker.process(path, pen, clip); 1053 1211 1054 1212 } else { // Some sort of dash 1055 dasher.process(path, pen );1213 dasher.process(path, pen, clip); 1056 1214 1057 1215 QVectorPath dashStroke(dasher.points(), 1058 1216 dasher.elementCount(), 1059 1217 dasher.elementTypes()); 1060 stroker.process(dashStroke, pen); 1061 } 1218 stroker.process(dashStroke, pen, clip); 1219 } 1220 1221 if (!stroker.vertexCount()) 1222 return; 1062 1223 1063 1224 if (opaque) { … … 1151 1312 1152 1313 1314 static const QRectF scaleRect(const QRectF &r, qreal sx, qreal sy) 1315 { 1316 return QRectF(r.x() * sx, r.y() * sy, r.width() * sx, r.height() * sy); 1317 } 1318 1153 1319 void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src) 1154 1320 { 1155 1321 Q_D(QGL2PaintEngineEx); 1322 QGLContext *ctx = d->ctx; 1323 1324 int max_texture_size = ctx->d_func()->maxTextureSize(); 1325 if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) { 1326 QPixmap scaled = pixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); 1327 1328 const qreal sx = scaled.width() / qreal(pixmap.width()); 1329 const qreal sy = scaled.height() / qreal(pixmap.height()); 1330 1331 drawPixmap(dest, scaled, scaleRect(src, sx, sy)); 1332 return; 1333 } 1334 1156 1335 ensureActive(); 1157 1336 d->transferMode(ImageDrawingMode); 1158 1337 1159 QGLContext *ctx = d->ctx;1160 1338 glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); 1161 1339 QGLTexture *texture = … … 1169 1347 1170 1348 bool isBitmap = pixmap.isQBitmap(); 1171 bool isOpaque = !isBitmap && !pixmap.hasAlpha Channel();1349 bool isOpaque = !isBitmap && !pixmap.hasAlpha(); 1172 1350 1173 1351 d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, … … 1180 1358 { 1181 1359 Q_D(QGL2PaintEngineEx); 1360 QGLContext *ctx = d->ctx; 1361 1362 int max_texture_size = ctx->d_func()->maxTextureSize(); 1363 if (image.width() > max_texture_size || image.height() > max_texture_size) { 1364 QImage scaled = image.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); 1365 1366 const qreal sx = scaled.width() / qreal(image.width()); 1367 const qreal sy = scaled.height() / qreal(image.height()); 1368 1369 drawImage(dest, scaled, scaleRect(src, sx, sy)); 1370 return; 1371 } 1372 1182 1373 ensureActive(); 1183 1374 d->transferMode(ImageDrawingMode); 1184 1375 1185 QGLContext *ctx = d->ctx;1186 1376 glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); 1377 1187 1378 QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); 1188 1379 GLuint id = texture->id; … … 1193 1384 } 1194 1385 1195 void QGL2PaintEngineEx::draw Texture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)1386 void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) 1196 1387 { 1197 1388 Q_D(QGL2PaintEngineEx); 1389 1390 ensureActive(); 1391 1392 QFontEngineGlyphCache::Type glyphType = textItem->fontEngine()->glyphFormat >= 0 1393 ? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat) 1394 : d->glyphCacheType; 1395 if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { 1396 if (d->device->alphaRequested() || state()->matrix.type() > QTransform::TxTranslate 1397 || (state()->composition_mode != QPainter::CompositionMode_Source 1398 && state()->composition_mode != QPainter::CompositionMode_SourceOver)) 1399 { 1400 glyphType = QFontEngineGlyphCache::Raster_A8; 1401 } 1402 } 1403 1404 d->drawCachedGlyphs(glyphType, textItem); 1405 } 1406 1407 bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) 1408 { 1409 Q_D(QGL2PaintEngineEx); 1410 if (!d->shaderManager) 1411 return false; 1412 1198 1413 ensureActive(); 1199 1414 d->transferMode(ImageDrawingMode); … … 1210 1425 state()->renderHints & QPainter::SmoothPixmapTransform, textureId); 1211 1426 d->drawTexture(dest, srcRect, size, false); 1427 return true; 1212 1428 } 1213 1429 … … 1246 1462 1247 1463 if (drawCached) { 1248 d->drawCachedGlyphs(p, glyphType, ti); 1464 QVarLengthArray<QFixedPoint> positions; 1465 QVarLengthArray<glyph_t> glyphs; 1466 QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); 1467 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); 1468 1469 { 1470 QStaticTextItem staticTextItem; 1471 staticTextItem.chars = const_cast<QChar *>(ti.chars); 1472 staticTextItem.setFontEngine(ti.fontEngine); 1473 staticTextItem.glyphs = glyphs.data(); 1474 staticTextItem.numChars = ti.num_chars; 1475 staticTextItem.numGlyphs = glyphs.size(); 1476 staticTextItem.glyphPositions = positions.data(); 1477 1478 d->drawCachedGlyphs(glyphType, &staticTextItem); 1479 } 1249 1480 return; 1250 1481 } … … 1253 1484 } 1254 1485 1255 void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, 1256 const QTextItemInt &ti) 1486 namespace { 1487 1488 class QOpenGLStaticTextUserData: public QStaticTextUserData 1489 { 1490 public: 1491 QOpenGLStaticTextUserData() 1492 : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) 1493 { 1494 } 1495 1496 ~QOpenGLStaticTextUserData() 1497 { 1498 } 1499 1500 QSize cacheSize; 1501 QGL2PEXVertexArray vertexCoordinateArray; 1502 QGL2PEXVertexArray textureCoordinateArray; 1503 QFontEngineGlyphCache::Type glyphType; 1504 }; 1505 1506 } 1507 1508 // #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO 1509 1510 void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, 1511 QStaticTextItem *staticTextItem) 1257 1512 { 1258 1513 Q_Q(QGL2PaintEngineEx); 1259 1514 1260 QVarLengthArray<QFixedPoint> positions; 1261 QVarLengthArray<glyph_t> glyphs; 1262 QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); 1263 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); 1515 QOpenGL2PaintEngineState *s = q->state(); 1516 1517 bool recreateVertexArrays = false; 1264 1518 1265 1519 QGLTextureGlyphCache *cache = 1266 (QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, glyphType, QTransform()); 1267 1520 (QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(ctx, glyphType, QTransform()); 1268 1521 if (!cache || cache->cacheType() != glyphType) { 1269 1522 cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); 1270 ti.fontEngine->setGlyphCache(ctx, cache); 1271 } 1272 1273 cache->setPaintEnginePrivate(this); 1274 cache->populate(ti, glyphs, positions); 1523 staticTextItem->fontEngine()->setGlyphCache(ctx, cache); 1524 recreateVertexArrays = true; 1525 } else if (cache->context() == 0) { // Old context has been destroyed, new context has same ptr value 1526 cache->setContext(ctx); 1527 } 1528 1529 if (staticTextItem->userDataNeedsUpdate) { 1530 recreateVertexArrays = true; 1531 } else if (staticTextItem->userData() == 0) { 1532 recreateVertexArrays = true; 1533 } else if (staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) { 1534 recreateVertexArrays = true; 1535 } else { 1536 QOpenGLStaticTextUserData *userData = static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData()); 1537 if (userData->glyphType != glyphType) 1538 recreateVertexArrays = true; 1539 } 1540 1541 // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. 1542 // If the cache size has changed, we do need to regenerate the vertices, but we don't need to repopulate the 1543 // cache so this text is performed before we test if the cache size has changed. 1544 if (recreateVertexArrays) { 1545 cache->setPaintEnginePrivate(this); 1546 if (!cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs, 1547 staticTextItem->glyphs, staticTextItem->glyphPositions)) { 1548 // No space in cache. We need to clear the cache and try again 1549 cache->clear(); 1550 cache->populate(staticTextItem->fontEngine(), staticTextItem->numGlyphs, 1551 staticTextItem->glyphs, staticTextItem->glyphPositions); 1552 } 1553 } 1275 1554 1276 1555 if (cache->width() == 0 || cache->height() == 0) … … 1284 1563 GLfloat dy = 1.0 / cache->height(); 1285 1564 1286 vertexCoordinateArray.clear(); 1287 textureCoordinateArray.clear(); 1288 1289 for (int i=0; i<glyphs.size(); ++i) { 1290 const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); 1291 int x = positions[i].x.toInt() + c.baseLineX - margin; 1292 int y = positions[i].y.toInt() - c.baseLineY - margin; 1293 1294 vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h)); 1295 textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy)); 1296 } 1297 1298 setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); 1299 setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); 1565 // Use global arrays by default 1566 QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray; 1567 QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray; 1568 1569 if (staticTextItem->useBackendOptimizations) { 1570 QOpenGLStaticTextUserData *userData = 0; 1571 1572 if (staticTextItem->userData() == 0 1573 || staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) { 1574 1575 userData = new QOpenGLStaticTextUserData(); 1576 staticTextItem->setUserData(userData); 1577 1578 } else { 1579 userData = static_cast<QOpenGLStaticTextUserData*>(staticTextItem->userData()); 1580 } 1581 1582 userData->glyphType = glyphType; 1583 1584 // Use cache if backend optimizations is turned on 1585 vertexCoordinates = &userData->vertexCoordinateArray; 1586 textureCoordinates = &userData->textureCoordinateArray; 1587 1588 QSize size(cache->width(), cache->height()); 1589 if (userData->cacheSize != size) { 1590 recreateVertexArrays = true; 1591 userData->cacheSize = size; 1592 } 1593 } 1594 1595 1596 if (recreateVertexArrays) { 1597 vertexCoordinates->clear(); 1598 textureCoordinates->clear(); 1599 1600 for (int i=0; i<staticTextItem->numGlyphs; ++i) { 1601 const QTextureGlyphCache::Coord &c = cache->coords.value(staticTextItem->glyphs[i]); 1602 int x = staticTextItem->glyphPositions[i].x.toInt() + c.baseLineX - margin; 1603 int y = staticTextItem->glyphPositions[i].y.toInt() - c.baseLineY - margin; 1604 1605 vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h)); 1606 textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy)); 1607 } 1608 1609 staticTextItem->userDataNeedsUpdate = false; 1610 } 1611 1612 if (elementIndices.size() < staticTextItem->numGlyphs*6) { 1613 Q_ASSERT(elementIndices.size() % 6 == 0); 1614 int j = elementIndices.size() / 6 * 4; 1615 while (j < staticTextItem->numGlyphs*4) { 1616 elementIndices.append(j + 0); 1617 elementIndices.append(j + 0); 1618 elementIndices.append(j + 1); 1619 elementIndices.append(j + 2); 1620 elementIndices.append(j + 3); 1621 elementIndices.append(j + 3); 1622 1623 j += 4; 1624 } 1625 1626 #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) 1627 if (elementIndicesVBOId == 0) 1628 glGenBuffers(1, &elementIndicesVBOId); 1629 1630 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); 1631 glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort), 1632 elementIndices.constData(), GL_STATIC_DRAW); 1633 #endif 1634 } else { 1635 #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) 1636 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); 1637 #endif 1638 } 1639 1640 setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data()); 1641 setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data()); 1300 1642 1301 1643 if (addOffset) { … … 1363 1705 updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); 1364 1706 1365 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); 1366 glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); 1707 #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) 1708 glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); 1709 #else 1710 glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); 1711 #endif 1367 1712 1368 1713 shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2); … … 1389 1734 //### TODO: Gamma correction 1390 1735 1391 glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); 1392 glBindTexture(GL_TEXTURE_2D, cache->texture()); 1393 updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); 1394 1395 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); 1396 glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); 1397 } 1398 1399 void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) 1736 QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest; 1737 if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { 1738 1739 glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); 1740 if (lastMaskTextureUsed != cache->texture()) { 1741 glBindTexture(GL_TEXTURE_2D, cache->texture()); 1742 lastMaskTextureUsed = cache->texture(); 1743 } 1744 1745 if (cache->filterMode() != filterMode) { 1746 if (filterMode == QGLTextureGlyphCache::Linear) { 1747 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1748 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1749 } else { 1750 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1751 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1752 } 1753 cache->setFilterMode(filterMode); 1754 } 1755 } 1756 1757 #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) 1758 glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); 1759 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1760 #else 1761 glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); 1762 #endif 1763 } 1764 1765 void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, 1766 QPainter::PixmapFragmentHints hints) 1400 1767 { 1401 1768 Q_D(QGL2PaintEngineEx); 1402 1769 // Use fallback for extended composition modes. 1403 1770 if (state()->composition_mode > QPainter::CompositionMode_Plus) { 1404 QPaintEngineEx::drawPixmap s(drawingData, dataCount, pixmap, hints);1771 QPaintEngineEx::drawPixmapFragments(fragments, fragmentCount, pixmap, hints); 1405 1772 return; 1406 1773 } 1407 1774 1408 1775 ensureActive(); 1409 d->drawPixmaps(drawingData, dataCount, pixmap, hints); 1410 } 1411 1412 1413 void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) 1776 int max_texture_size = d->ctx->d_func()->maxTextureSize(); 1777 if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) { 1778 QPixmap scaled = pixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); 1779 d->drawPixmapFragments(fragments, fragmentCount, scaled, hints); 1780 } else { 1781 d->drawPixmapFragments(fragments, fragmentCount, pixmap, hints); 1782 } 1783 } 1784 1785 1786 void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments, 1787 int fragmentCount, const QPixmap &pixmap, 1788 QPainter::PixmapFragmentHints hints) 1414 1789 { 1415 1790 GLfloat dx = 1.0f / pixmap.size().width(); … … 1432 1807 bool allOpaque = true; 1433 1808 1434 for (int i = 0; i < dataCount; ++i) {1809 for (int i = 0; i < fragmentCount; ++i) { 1435 1810 qreal s = 0; 1436 1811 qreal c = 1; 1437 if ( drawingData[i].rotation != 0) {1438 s = qFastSin( drawingData[i].rotation * Q_PI / 180);1439 c = qFastCos( drawingData[i].rotation * Q_PI / 180);1440 } 1441 1442 qreal right = 0.5 * drawingData[i].scaleX * drawingData[i].source.width();1443 qreal bottom = 0.5 * drawingData[i].scaleY * drawingData[i].source.height();1812 if (fragments[i].rotation != 0) { 1813 s = qFastSin(fragments[i].rotation * Q_PI / 180); 1814 c = qFastCos(fragments[i].rotation * Q_PI / 180); 1815 } 1816 1817 qreal right = 0.5 * fragments[i].scaleX * fragments[i].width; 1818 qreal bottom = 0.5 * fragments[i].scaleY * fragments[i].height; 1444 1819 QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c); 1445 1820 QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c); 1446 1821 1447 vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); 1448 vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y()); 1449 vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); 1450 vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y()); 1451 vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y()); 1452 vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y()); 1453 1454 QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy, 1455 drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy); 1456 1457 textureCoordinateArray.lineToArray(src.right, src.bottom); 1458 textureCoordinateArray.lineToArray(src.right, src.top); 1459 textureCoordinateArray.lineToArray(src.left, src.top); 1460 textureCoordinateArray.lineToArray(src.left, src.top); 1461 textureCoordinateArray.lineToArray(src.left, src.bottom); 1462 textureCoordinateArray.lineToArray(src.right, src.bottom); 1463 1464 qreal opacity = drawingData[i].opacity * q->state()->opacity; 1822 vertexCoordinateArray.addVertex(bottomRight.x + fragments[i].x, bottomRight.y + fragments[i].y); 1823 vertexCoordinateArray.addVertex(-bottomLeft.x + fragments[i].x, -bottomLeft.y + fragments[i].y); 1824 vertexCoordinateArray.addVertex(-bottomRight.x + fragments[i].x, -bottomRight.y + fragments[i].y); 1825 vertexCoordinateArray.addVertex(-bottomRight.x + fragments[i].x, -bottomRight.y + fragments[i].y); 1826 vertexCoordinateArray.addVertex(bottomLeft.x + fragments[i].x, bottomLeft.y + fragments[i].y); 1827 vertexCoordinateArray.addVertex(bottomRight.x + fragments[i].x, bottomRight.y + fragments[i].y); 1828 1829 QGLRect src(fragments[i].sourceLeft * dx, fragments[i].sourceTop * dy, 1830 (fragments[i].sourceLeft + fragments[i].width) * dx, 1831 (fragments[i].sourceTop + fragments[i].height) * dy); 1832 1833 textureCoordinateArray.addVertex(src.right, src.bottom); 1834 textureCoordinateArray.addVertex(src.right, src.top); 1835 textureCoordinateArray.addVertex(src.left, src.top); 1836 textureCoordinateArray.addVertex(src.left, src.top); 1837 textureCoordinateArray.addVertex(src.left, src.bottom); 1838 textureCoordinateArray.addVertex(src.right, src.bottom); 1839 1840 qreal opacity = fragments[i].opacity * q->state()->opacity; 1465 1841 opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; 1466 1842 allOpaque &= (opacity >= 0.99f); … … 1475 1851 // Flip texture y-coordinate. 1476 1852 QGLPoint *data = textureCoordinateArray.data(); 1477 for (int i = 0; i < 6 * dataCount; ++i)1853 for (int i = 0; i < 6 * fragmentCount; ++i) 1478 1854 data[i].y = 1 - data[i].y; 1479 1855 } … … 1482 1858 1483 1859 bool isBitmap = pixmap.isQBitmap(); 1484 bool isOpaque = !isBitmap && (!pixmap.hasAlpha Channel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque;1860 bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; 1485 1861 1486 1862 updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, … … 1489 1865 // Setup for texture drawing 1490 1866 currentBrush = noBrush; 1491 shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc); 1867 shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc 1868 : QGLEngineShaderManager::ImageSrc); 1492 1869 if (prepareForDraw(isOpaque)) 1493 1870 shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); … … 1498 1875 } 1499 1876 1500 glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount);1877 glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount); 1501 1878 } 1502 1879 … … 1523 1900 d->brushTextureDirty = true; 1524 1901 d->brushUniformsDirty = true; 1902 d->matrixUniformDirty = true; 1525 1903 d->matrixDirty = true; 1526 1904 d->compositionModeDirty = true; … … 1560 1938 #if defined(Q_WS_WIN) 1561 1939 if (qt_cleartype_enabled) 1940 #endif 1941 #if defined(Q_WS_MAC) 1942 if (qt_applefontsmoothing_enabled) 1562 1943 #endif 1563 1944 d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask; … … 1605 1986 d->unusedVBOSToClean.clear(); 1606 1987 } 1988 if (!d->unusedIBOSToClean.isEmpty()) { 1989 glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData()); 1990 d->unusedIBOSToClean.clear(); 1991 } 1607 1992 #endif 1608 1993 … … 1626 2011 glViewport(0, 0, d->width, d->height); 1627 2012 d->needsSync = false; 2013 d->lastMaskTextureUsed = 0; 1628 2014 d->shaderManager->setDirty(); 1629 2015 d->ctx->d_func()->syncGlState(); … … 1806 2192 QRectF rect(points[0], points[2]); 1807 2193 1808 if (state()->matrix.type() <= QTransform::TxScale) { 2194 if (state()->matrix.type() <= QTransform::TxScale 2195 || (state()->matrix.type() == QTransform::TxRotate 2196 && qFuzzyIsNull(state()->matrix.m11()) 2197 && qFuzzyIsNull(state()->matrix.m22()))) 2198 { 1809 2199 state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect()); 1810 2200 d->updateClipScissorTest();
Note:
See TracChangeset
for help on using the changeset viewer.