Changeset 846 for trunk/src/opengl/gl2paintengineex
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 16 edited
- 2 copied
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/qgl2pexvertexarray.cpp
r651 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) … … 62 62 } 63 63 64 void QGL2PEXVertexArray::addRect(const QRectF &rect)65 {66 vertexArray << rect.topLeft() << rect.topRight() << rect.bottomRight()67 << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();68 }69 70 64 void QGL2PEXVertexArray::addClosingLine(int index) 71 65 { 72 if (QPointF(vertexArray.at(index)) != QPointF(vertexArray.last())) 73 vertexArray.add(vertexArray.at(index)); 66 QPointF point(vertexArray.at(index)); 67 if (point != QPointF(vertexArray.last())) 68 vertexArray.add(point); 74 69 } 75 70 … … 146 141 int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6)); 147 142 if (threshold < 3) threshold = 3; 148 qreal one_over_threshold_minus_1 = 1.f/ (threshold - 1);143 qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1); 149 144 for (int t=0; t<threshold; ++t) { 150 145 QPointF pt = b.pointAt(t * one_over_threshold_minus_1); -
trunk/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
r651 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) … … 94 94 GLfloat bottom; 95 95 96 operator QRectF() {return QRectF(left, top, right-left, bottom-top);}96 operator QRectF() const {return QRectF(left, top, right-left, bottom-top);} 97 97 }; 98 98 … … 101 101 public: 102 102 QGL2PEXVertexArray() : 103 vertexArray(0), vertexArrayStops(0), 103 104 maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10), 104 boundingRectDirty(true) {} 105 boundingRectDirty(true) 106 { } 107 108 inline void addRect(const QRectF &rect) 109 { 110 qreal top = rect.top(); 111 qreal left = rect.left(); 112 qreal bottom = rect.bottom(); 113 qreal right = rect.right(); 114 115 vertexArray << QGLPoint(left, top) 116 << QGLPoint(right, top) 117 << QGLPoint(right, bottom) 118 << QGLPoint(right, bottom) 119 << QGLPoint(left, bottom) 120 << QGLPoint(left, top); 121 } 105 122 106 void addRect(const QRectF &rect); 123 inline void addQuad(const QRectF &rect) 124 { 125 qreal top = rect.top(); 126 qreal left = rect.left(); 127 qreal bottom = rect.bottom(); 128 qreal right = rect.right(); 129 130 vertexArray << QGLPoint(left, top) 131 << QGLPoint(right, top) 132 << QGLPoint(left, bottom) 133 << QGLPoint(right, bottom); 134 135 } 136 137 inline void addVertex(const GLfloat x, const GLfloat y) 138 { 139 vertexArray.add(QGLPoint(x, y)); 140 } 141 107 142 void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true); 108 143 void clear(); -
trunk/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp
r651 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) -
trunk/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h
r651 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) -
trunk/src/opengl/gl2paintengineex/qglengineshadermanager.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) … … 42 42 #include "qglengineshadermanager_p.h" 43 43 #include "qglengineshadersource_p.h" 44 #include "qpaintengineex_opengl2_p.h" 44 45 45 46 #if defined(QT_DEBUG) … … 97 98 code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader; 98 99 code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader; 100 code[ComplexGeometryPositionOnlyVertexShader] = qglslComplexGeometryPositionOnlyVertexShader; 99 101 code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader; 100 102 code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader; … … 248 250 249 251 // The address returned here will only be valid until next time this function is called. 252 // The program is return bound. 250 253 QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) 251 254 { … … 255 258 // Move the program to the top of the list as a poor-man's cache algo 256 259 cachedPrograms.move(i, 0); 260 cachedProg->program->bind(); 257 261 return cachedProg; 258 262 } … … 330 334 if (newProg->useOpacityAttribute) 331 335 newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); 332 if (newProg->usePmvMatrix ) {336 if (newProg->usePmvMatrixAttribute) { 333 337 newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); 334 338 newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); … … 355 359 break; 356 360 } 361 362 newProg->program->bind(); 363 364 if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) { 365 GLuint location = newProg->program->uniformLocation("maskTexture"); 366 newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); 367 } 368 357 369 if (cachedPrograms.count() > 30) { 358 370 // The cache is full, so delete the last 5 programs in the list. … … 404 416 : ctx(context), 405 417 shaderProgNeedsChanging(true), 418 complexGeometry(false), 406 419 srcPixelType(Qt::NoBrush), 407 420 opacityMode(NoOpacity), … … 445 458 "invertedTextureSize", 446 459 "brushTransform", 447 "brushTexture" 460 "brushTexture", 461 "matrix" 448 462 }; 449 463 … … 753 767 requiredProgram.useTextureCoords = texCoords; 754 768 requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); 755 requiredProgram.usePmvMatrix = true; 769 if (complexGeometry && srcPixelType == Qt::SolidPattern) { 770 requiredProgram.positionVertexShader = QGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader; 771 requiredProgram.usePmvMatrixAttribute = false; 772 } else { 773 requiredProgram.usePmvMatrixAttribute = true; 774 775 // Force complexGeometry off, since we currently don't support that mode for 776 // non-solid brushes 777 complexGeometry = false; 778 } 756 779 757 780 // At this point, requiredProgram is fully populated so try to find the program in the cache 758 781 currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); 759 782 760 if (currentShaderProg) { 761 currentShaderProg->program->bind(); 762 if (useCustomSrc) 763 customSrcStage->setUniforms(currentShaderProg->program); 783 if (currentShaderProg && useCustomSrc) { 784 customSrcStage->setUniforms(currentShaderProg->program); 764 785 } 765 786 -
trunk/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
r651 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) … … 73 73 calculations which logically belong in the fragment shader have been moved 74 74 into the vertex shader to improve performance. This is why the position 75 calculation is in a sep erate shader. Not only does it calculate the75 calculation is in a separate shader. Not only does it calculate the 76 76 position, but it also calculates some data to be passed to the fragment 77 77 shader as a varying. It is optimal to move as much of the calculation as … … 273 273 UntransformedPositionVertexShader, 274 274 PositionOnlyVertexShader, 275 ComplexGeometryPositionOnlyVertexShader, 275 276 PositionWithPatternBrushVertexShader, 276 277 PositionWithLinearGradientBrushVertexShader, … … 401 402 bool useTextureCoords; 402 403 bool useOpacityAttribute; 403 bool usePmvMatrix ;404 bool usePmvMatrixAttribute; 404 405 405 406 bool operator==(const QGLEngineShaderProg& other) { … … 447 448 BrushTransform, 448 449 BrushTexture, 450 Matrix, 449 451 NumUniforms 450 452 }; … … 456 458 }; 457 459 458 // There are optimi sations we can do, depending on the brush transform:460 // There are optimizations we can do, depending on the brush transform: 459 461 // 1) May not have to apply perspective-correction 460 462 // 2) Can use lower precision for matrix … … 475 477 void useSimpleProgram(); 476 478 void useBlitProgram(); 479 void setHasComplexGeometry(bool hasComplexGeometry) 480 { 481 complexGeometry = hasComplexGeometry; 482 shaderProgNeedsChanging = true; 483 } 484 bool hasComplexGeometry() const 485 { 486 return complexGeometry; 487 } 477 488 478 489 QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen … … 488 499 QGLContext* ctx; 489 500 bool shaderProgNeedsChanging; 501 bool complexGeometry; 490 502 491 503 // Current state variables which influence the choice of shader: -
trunk/src/opengl/gl2paintengineex/qglengineshadersource_p.h
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) … … 107 107 gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ 108 108 }\n"; 109 110 static const char* const qglslComplexGeometryPositionOnlyVertexShader = "\n\ 111 uniform highp mat3 matrix; \n\ 112 attribute highp vec2 vertexCoordsArray; \n\ 113 void setPosition(void) \n\ 114 { \n\ 115 gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ 116 } \n"; 109 117 110 118 static const char* const qglslUntransformedPositionVertexShader = "\n\ … … 275 283 uniform highp vec2 invertedTextureSize; \n\ 276 284 uniform highp mat3 brushTransform; \n\ 277 varying highp vec2 textureCoords; \n\285 varying highp vec2 brushTextureCoords; \n\ 278 286 void setPosition(void) \n\ 279 287 { \n\ … … 285 293 mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ 286 294 gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ 287 textureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\295 brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ 288 296 }\n"; 289 297 … … 296 304 // TODO: Special case POT textures which don't need this emulation 297 305 static const char* const qglslTextureBrushSrcFragmentShader = "\n\ 298 varying highp vec2 textureCoords; \n\306 varying highp vec2 brushTextureCoords; \n\ 299 307 uniform lowp sampler2D brushTexture; \n\ 300 308 lowp vec4 srcPixel() { \n\ 301 return texture2D(brushTexture, fract( textureCoords)); \n\309 return texture2D(brushTexture, fract(brushTextureCoords)); \n\ 302 310 }\n"; 303 311 #else 304 312 static const char* const qglslTextureBrushSrcFragmentShader = "\n\ 305 varying highp vec2 textureCoords; \n\313 varying highp vec2 brushTextureCoords; \n\ 306 314 uniform lowp sampler2D brushTexture; \n\ 307 315 lowp vec4 srcPixel() \n\ 308 316 { \n\ 309 return texture2D(brushTexture, textureCoords); \n\317 return texture2D(brushTexture, brushTextureCoords); \n\ 310 318 }\n"; 311 319 #endif 312 320 313 321 static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\ 314 varying highp vec2 textureCoords; \n\322 varying highp vec2 brushTextureCoords; \n\ 315 323 uniform lowp vec4 patternColor; \n\ 316 324 uniform lowp sampler2D brushTexture; \n\ 317 325 lowp vec4 srcPixel() \n\ 318 326 { \n\ 319 return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \n\327 return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\ 320 328 }\n"; 321 329 … … 333 341 lowp vec4 srcPixel() \n\ 334 342 { \n" 335 #ifdef QT_OPENGL_ES_2336 // work-around for driver bug337 "return 1.0 * texture2D(imageTexture, textureCoords); \n"338 #else339 343 "return texture2D(imageTexture, textureCoords); \n" 340 #endif341 344 "}\n"; 342 345 -
trunk/src/opengl/gl2paintengineex/qglgradientcache.cpp
r651 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) … … 40 40 ****************************************************************************/ 41 41 42 #include "qglgradientcache_p.h" 42 43 #include <private/qdrawhelper_p.h> 43 44 #include <private/qgl_p.h> 44 45 45 #include "qglgradientcache_p.h"46 46 47 47 QT_BEGIN_NAMESPACE -
trunk/src/opengl/gl2paintengineex/qglgradientcache_p.h
r651 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) -
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(); -
trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
r651 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) … … 124 124 virtual void transformChanged(); 125 125 126 virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);127 126 virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); 128 virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); 127 virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, 128 QPainter::PixmapFragmentHints hints); 129 129 virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, 130 130 Qt::ImageConversionFlags flags = Qt::AutoColor); … … 134 134 virtual void clip(const QVectorPath &path, Qt::ClipOperation op); 135 135 136 virtual void drawStaticTextItem(QStaticTextItem *textItem); 137 138 bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); 136 139 137 140 Type type() const { return OpenGL2; } … … 149 152 void endNativePainting(); 150 153 154 void invalidateState(); 155 151 156 QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype); 152 157 153 158 void setRenderTextActive(bool); 154 159 160 bool isNativePaintingActive() const; 155 161 private: 156 162 Q_DISABLE_COPY(QGL2PaintEngineEx) 157 163 }; 158 159 164 160 165 class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate … … 174 179 ctx(0), 175 180 useSystemClip(true), 181 elementIndicesVBOId(0), 182 opacityArray(0), 176 183 snapToPixelGrid(false), 177 184 addOffset(false), 178 inverseScale(1) 185 nativePaintingActive(false), 186 inverseScale(1), 187 lastMaskTextureUsed(0) 179 188 { } 180 189 … … 194 203 void stroke(const QVectorPath &path, const QPen &pen); 195 204 void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); 196 void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints); 197 void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti); 205 void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, 206 QPainter::PixmapFragmentHints hints); 207 void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem); 198 208 199 209 // Calls glVertexAttributePointer if the pointer has changed … … 254 264 bool brushUniformsDirty; 255 265 bool opacityUniformDirty; 266 bool matrixUniformDirty; 256 267 257 268 bool stencilClean; // Has the stencil not been used for clipping so far? … … 264 275 const QBrush noBrush; 265 276 277 QPixmap currentBrushPixmap; 278 266 279 QGL2PEXVertexArray vertexCoordinateArray; 267 280 QGL2PEXVertexArray textureCoordinateArray; 281 QVector<GLushort> elementIndices; 282 GLuint elementIndicesVBOId; 268 283 QDataBuffer<GLfloat> opacityArray; 269 284 GLfloat staticVertexCoordinateArray[8]; … … 272 287 bool snapToPixelGrid; 273 288 bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix 289 bool nativePaintingActive; 274 290 GLfloat pmvMatrix[3][3]; 275 291 GLfloat inverseScale; 276 292 277 293 GLuint lastTextureUsed; 294 GLuint lastMaskTextureUsed; 278 295 279 296 bool needsSync; … … 294 311 QSet<QVectorPath::CacheEntry *> pathCaches; 295 312 QVector<GLuint> unusedVBOSToClean; 313 QVector<GLuint> unusedIBOSToClean; 296 314 297 315 const GLfloat *vertexAttribPointers[3]; -
trunk/src/opengl/gl2paintengineex/qtextureglyphcache_gl.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) … … 43 43 #include "qpaintengineex_opengl2_p.h" 44 44 45 #if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL) 46 #include "private/qeglcontext_p.h" 47 #endif 48 45 49 QT_BEGIN_NAMESPACE 46 50 … … 50 54 51 55 QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) 52 : Q TextureGlyphCache(type, matrix)53 , ctx( context)56 : QImageTextureGlyphCache(type, matrix) 57 , ctx(0) 54 58 , m_width(0) 55 59 , m_height(0) 56 { 57 glGenFramebuffers(1, &m_fbo); 60 , m_filterMode(Nearest) 61 { 62 setContext(context); 63 } 64 65 void QGLTextureGlyphCache::setContext(QGLContext *context) 66 { 67 ctx = context; 68 69 // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where 70 // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The 71 // workaround is to use a system-memory copy of the glyph cache for this device. 72 // Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and 73 // be slower, so that is not desireable. 74 if (!ctx->d_ptr->workaround_brokenFBOReadBack) 75 glGenFramebuffers(1, &m_fbo); 76 58 77 connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)), 59 78 SLOT(contextDestroyed(const QGLContext*))); 60 79 } 61 80 62 QGLTextureGlyphCache::~QGLTextureGlyphCache() 81 void QGLTextureGlyphCache::clear() 63 82 { 64 83 if (ctx) { 65 84 QGLShareContextScope scope(ctx); 66 glDeleteFramebuffers(1, &m_fbo);67 85 68 86 if (m_width || m_height) 69 87 glDeleteTextures(1, &m_texture); 70 } 88 89 m_texture = 0; 90 m_width = 0; 91 m_height = 0; 92 m_w = 0; 93 m_h = 0; 94 m_cx = 0; 95 m_cy = 0; 96 m_currentRowHeight = 0; 97 coords.clear(); 98 } 99 100 } 101 102 QGLTextureGlyphCache::~QGLTextureGlyphCache() 103 { 104 if (ctx) { 105 QGLShareContextScope scope(ctx); 106 107 if (!ctx->d_ptr->workaround_brokenFBOReadBack) 108 glDeleteFramebuffers(1, &m_fbo); 109 } 110 111 clear(); 71 112 } 72 113 73 114 void QGLTextureGlyphCache::createTextureData(int width, int height) 74 115 { 116 // create in QImageTextureGlyphCache baseclass is meant to be called 117 // only to create the initial image and does not preserve the content, 118 // so we don't call when this function is called from resize. 119 if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull()) 120 QImageTextureGlyphCache::createTextureData(width, height); 121 122 // Make the lower glyph texture size 16 x 16. 123 if (width < 16) 124 width = 16; 125 if (height < 16) 126 height = 16; 127 75 128 glGenTextures(1, &m_texture); 76 129 glBindTexture(GL_TEXTURE_2D, m_texture); … … 79 132 m_height = height; 80 133 81 QVarLengthArray<uchar> data(width * height); 82 for (int i = 0; i < data.size(); ++i) 83 data[i] = 0; 84 85 if (m_type == QFontEngineGlyphCache::Raster_RGBMask) 86 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]); 87 else 134 if (m_type == QFontEngineGlyphCache::Raster_RGBMask) { 135 QVarLengthArray<uchar> data(width * height * 4); 136 for (int i = 0; i < data.size(); ++i) 137 data[i] = 0; 138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); 139 } else { 140 QVarLengthArray<uchar> data(width * height); 141 for (int i = 0; i < data.size(); ++i) 142 data[i] = 0; 88 143 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]); 144 } 89 145 90 146 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 91 147 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 148 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 149 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 150 m_filterMode = Nearest; 92 151 } 93 152 94 153 void QGLTextureGlyphCache::resizeTextureData(int width, int height) 95 154 { 155 int oldWidth = m_width; 156 int oldHeight = m_height; 157 158 // Make the lower glyph texture size 16 x 16. 159 if (width < 16) 160 width = 16; 161 if (height < 16) 162 height = 16; 163 164 GLuint oldTexture = m_texture; 165 createTextureData(width, height); 166 167 if (ctx->d_ptr->workaround_brokenFBOReadBack) { 168 QImageTextureGlyphCache::resizeTextureData(width, height); 169 Q_ASSERT(image().depth() == 8); 170 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); 171 glDeleteTextures(1, &oldTexture); 172 return; 173 } 174 96 175 // ### the QTextureGlyphCache API needs to be reworked to allow 97 176 // ### resizeTextureData to fail 98 99 int oldWidth = m_width;100 int oldHeight = m_height;101 102 GLuint oldTexture = m_texture;103 createTextureData(width, height);104 177 105 178 glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); … … 114 187 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 115 188 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 189 m_filterMode = Nearest; 116 190 glBindTexture(GL_TEXTURE_2D, 0); 117 191 glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, … … 160 234 glBindTexture(GL_TEXTURE_2D, m_texture); 161 235 162 #ifdef QT_OPENGL_ES_2163 QDataBuffer<uchar> buffer(4*oldWidth*oldHeight);164 buffer.resize(4*oldWidth*oldHeight);165 glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());166 167 // do an in-place conversion from GL_RGBA to GL_ALPHA168 for (int i=0; i<oldWidth*oldHeight; ++i)169 buffer.data()[i] = buffer.at(4*i + 3);170 171 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight,172 GL_ALPHA, GL_UNSIGNED_BYTE, buffer.data());173 #else174 236 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); 175 #endif176 237 177 238 glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, … … 188 249 void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph) 189 250 { 251 if (ctx->d_ptr->workaround_brokenFBOReadBack) { 252 QImageTextureGlyphCache::fillTexture(c, glyph); 253 254 glBindTexture(GL_TEXTURE_2D, m_texture); 255 const QImage &texture = image(); 256 const uchar *bits = texture.constBits(); 257 bits += c.y * texture.bytesPerLine() + c.x; 258 for (int i=0; i<c.h; ++i) { 259 glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits); 260 bits += texture.bytesPerLine(); 261 } 262 263 return; 264 } 265 190 266 QImage mask = textureMapForGlyph(glyph); 191 267 const int maskWidth = mask.width(); … … 218 294 glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits()); 219 295 } else { 220 #ifdef QT_OPENGL_ES2221 glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());222 #else223 296 // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is 224 297 // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista … … 232 305 for (int i = 0; i < maskHeight; ++i) 233 306 glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i)); 234 #endif 235 } 236 } 237 238 int QGLTextureGlyphCache::glyphMargin() const 239 { 240 #if defined(Q_WS_MAC) 241 return 2; 242 #elif defined (Q_WS_X11) 243 return 0; 244 #else 245 return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0; 246 #endif 247 } 248 307 } 308 } 309 310 int QGLTextureGlyphCache::glyphPadding() const 311 { 312 return 1; 313 } 314 315 int QGLTextureGlyphCache::maxTextureWidth() const 316 { 317 return ctx->d_ptr->maxTextureSize(); 318 } 319 320 int QGLTextureGlyphCache::maxTextureHeight() const 321 { 322 if (ctx->d_ptr->workaround_brokenTexSubImage) 323 return qMin(1024, ctx->d_ptr->maxTextureSize()); 324 else 325 return ctx->d_ptr->maxTextureSize(); 326 } 249 327 QT_END_NAMESPACE -
trunk/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
r651 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) … … 63 63 class QGL2PaintEngineExPrivate; 64 64 65 class Q GLTextureGlyphCache : public QObject, public QTextureGlyphCache65 class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache 66 66 { 67 67 Q_OBJECT … … 73 73 virtual void resizeTextureData(int width, int height); 74 74 virtual void fillTexture(const Coord &c, glyph_t glyph); 75 virtual int glyphMargin() const; 75 virtual int glyphPadding() const; 76 virtual int maxTextureWidth() const; 77 virtual int maxTextureHeight() const; 76 78 77 79 inline GLuint texture() const { return m_texture; } … … 82 84 inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } 83 85 86 enum FilterMode { 87 Nearest, 88 Linear 89 }; 90 FilterMode filterMode() const { return m_filterMode; } 91 void setFilterMode(FilterMode m) { m_filterMode = m; } 92 93 void setContext(QGLContext *context); 94 QGLContext *context() const { return ctx; } 84 95 85 96 public Q_SLOTS: … … 91 102 // destroy the fbo and texture here, but since the context 92 103 // is about to be destroyed, the GL server will do the 93 // clean up for us anyway 104 // clean up for us anyway. We reset everything, so that the 105 // glyph cache object can be reused later by setting a new 106 // context on it. 94 107 m_fbo = 0; 95 108 m_texture = 0; 96 109 ctx = 0; 110 m_width = 0; 111 m_height = 0; 112 m_w = 0; 113 m_h = 0; 114 m_cx = 0; 115 m_cy = 0; 116 m_currentRowHeight = 0; 117 coords.clear(); 97 118 } else { 98 119 // since the context holding the texture is shared, and … … 103 124 } 104 125 } 126 127 void clear(); 105 128 106 129 private: … … 116 139 117 140 QGLShaderProgram *m_program; 141 142 FilterMode m_filterMode; 118 143 }; 119 144 -
trunk/src/opengl/gl2paintengineex/qtriangulatingstroker.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) … … 74 74 75 75 76 void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen )76 void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &) 77 77 { 78 78 const qreal *pts = path.points(); … … 112 112 // 113 113 // The curvyness value of PI/14 was based on, 114 // arcLength =2*PI*r/4=PI/2 and splitting length into somewhere114 // arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere 115 115 // between 3 and 8 where 5 seemed to be give pretty good results 116 116 // hence: Q_PI/14. Lower divisors will give more detail at the … … 482 482 483 483 QDashedStrokeProcessor::QDashedStrokeProcessor() 484 : m_dash_stroker(0), m_inv_scale(1) 484 : m_points(0), m_types(0), 485 m_dash_stroker(0), m_inv_scale(1) 485 486 { 486 487 m_dash_stroker.setMoveToHook(qdashprocessor_moveTo); … … 489 490 } 490 491 491 void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen )492 void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, const QRectF &clip) 492 493 { 493 494 … … 496 497 int count = path.elementCount(); 497 498 499 bool cosmetic = pen.isCosmetic(); 500 498 501 m_points.reset(); 499 502 m_types.reset(); 503 m_points.reserve(path.elementCount()); 504 m_types.reserve(path.elementCount()); 500 505 501 506 qreal width = qpen_widthf(pen); … … 504 509 505 510 m_dash_stroker.setDashPattern(pen.dashPattern()); 506 m_dash_stroker.setStrokeWidth(pen.isCosmetic() ? width * m_inv_scale : width); 511 m_dash_stroker.setStrokeWidth(cosmetic ? width * m_inv_scale : width); 512 m_dash_stroker.setDashOffset(pen.dashOffset()); 507 513 m_dash_stroker.setMiterLimit(pen.miterLimit()); 508 qreal curvyness = sqrt(width) * m_inv_scale / 8; 514 m_dash_stroker.setClipRect(clip); 515 516 float curvynessAdd, curvynessMul, roundness = 0; 517 518 // simplfy pens that are thin in device size (2px wide or less) 519 if (width < 2.5 && (cosmetic || m_inv_scale == 1)) { 520 curvynessAdd = 0.5; 521 curvynessMul = CURVE_FLATNESS / m_inv_scale; 522 roundness = 1; 523 } else if (cosmetic) { 524 curvynessAdd= width / 2; 525 curvynessMul= CURVE_FLATNESS; 526 roundness = qMax<int>(4, width * CURVE_FLATNESS); 527 } else { 528 curvynessAdd = width * m_inv_scale; 529 curvynessMul = CURVE_FLATNESS / m_inv_scale; 530 roundness = qMax<int>(4, width * curvynessMul); 531 } 509 532 510 533 if (count < 2) … … 541 564 *(((const QPointF *) pts) + 2)); 542 565 QRectF bounds = b.bounds(); 543 int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * curvyness); 566 float rad = qMax(bounds.width(), bounds.height()); 567 int threshold = qMin<float>(64, (rad + curvynessAdd) * curvynessMul); 544 568 if (threshold < 4) 545 569 threshold = 4; 570 546 571 qreal threshold_minus_1 = threshold - 1; 547 572 for (int i=0; i<threshold; ++i) { -
trunk/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h
r651 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) … … 55 55 { 56 56 public: 57 void process(const QVectorPath &path, const QPen &pen); 57 QTriangulatingStroker() : m_vertices(0) {} 58 void process(const QVectorPath &path, const QPen &pen, const QRectF &clip); 58 59 59 60 inline int vertexCount() const { return m_vertices.size(); } … … 97 98 QDashedStrokeProcessor(); 98 99 99 void process(const QVectorPath &path, const QPen &pen );100 void process(const QVectorPath &path, const QPen &pen, const QRectF &clip); 100 101 101 102 inline void addElement(QPainterPath::ElementType type, qreal x, qreal y) {
Note:
See TracChangeset
for help on using the changeset viewer.