Changeset 846 for trunk/src/opengl


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
1 deleted
69 edited
5 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6262}
    6363
    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 
    7064void QGL2PEXVertexArray::addClosingLine(int index)
    7165{
    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);
    7469}
    7570
     
    146141                int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6));
    147142                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);
    149144                for (int t=0; t<threshold; ++t) {
    150145                    QPointF pt = b.pointAt(t * one_over_threshold_minus_1);
  • trunk/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9494    GLfloat bottom;
    9595
    96     operator QRectF() {return QRectF(left, top, right-left, bottom-top);}
     96    operator QRectF() const {return QRectF(left, top, right-left, bottom-top);}
    9797};
    9898
     
    101101public:
    102102    QGL2PEXVertexArray() :
     103        vertexArray(0), vertexArrayStops(0),
    103104        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    }
    105122
    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
    107142    void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
    108143    void clear();
  • trunk/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/gl2paintengineex/qglengineshadermanager.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4242#include "qglengineshadermanager_p.h"
    4343#include "qglengineshadersource_p.h"
     44#include "qpaintengineex_opengl2_p.h"
    4445
    4546#if defined(QT_DEBUG)
     
    9798        code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
    9899        code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
     100        code[ComplexGeometryPositionOnlyVertexShader] = qglslComplexGeometryPositionOnlyVertexShader;
    99101        code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
    100102        code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
     
    248250
    249251// The address returned here will only be valid until next time this function is called.
     252// The program is return bound.
    250253QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
    251254{
     
    255258            // Move the program to the top of the list as a poor-man's cache algo
    256259            cachedPrograms.move(i, 0);
     260            cachedProg->program->bind();
    257261            return cachedProg;
    258262        }
     
    330334        if (newProg->useOpacityAttribute)
    331335            newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
    332         if (newProg->usePmvMatrix) {
     336        if (newProg->usePmvMatrixAttribute) {
    333337            newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
    334338            newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
     
    355359            break;
    356360        }
     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
    357369        if (cachedPrograms.count() > 30) {
    358370            // The cache is full, so delete the last 5 programs in the list.
     
    404416    : ctx(context),
    405417      shaderProgNeedsChanging(true),
     418      complexGeometry(false),
    406419      srcPixelType(Qt::NoBrush),
    407420      opacityMode(NoOpacity),
     
    445458        "invertedTextureSize",
    446459        "brushTransform",
    447         "brushTexture"
     460        "brushTexture",
     461        "matrix"
    448462    };
    449463
     
    753767    requiredProgram.useTextureCoords = texCoords;
    754768    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    }
    756779
    757780    // At this point, requiredProgram is fully populated so try to find the program in the cache
    758781    currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
    759782
    760     if (currentShaderProg) {
    761         currentShaderProg->program->bind();
    762         if (useCustomSrc)
    763             customSrcStage->setUniforms(currentShaderProg->program);
     783    if (currentShaderProg && useCustomSrc) {
     784        customSrcStage->setUniforms(currentShaderProg->program);
    764785    }
    765786
  • trunk/src/opengl/gl2paintengineex/qglengineshadermanager_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7373    calculations which logically belong in the fragment shader have been moved
    7474    into the vertex shader to improve performance. This is why the position
    75     calculation is in a seperate shader. Not only does it calculate the
     75    calculation is in a separate shader. Not only does it calculate the
    7676    position, but it also calculates some data to be passed to the fragment
    7777    shader as a varying. It is optimal to move as much of the calculation as
     
    273273        UntransformedPositionVertexShader,
    274274        PositionOnlyVertexShader,
     275        ComplexGeometryPositionOnlyVertexShader,
    275276        PositionWithPatternBrushVertexShader,
    276277        PositionWithLinearGradientBrushVertexShader,
     
    401402    bool                useTextureCoords;
    402403    bool                useOpacityAttribute;
    403     bool                usePmvMatrix;
     404    bool                usePmvMatrixAttribute;
    404405
    405406    bool operator==(const QGLEngineShaderProg& other) {
     
    447448        BrushTransform,
    448449        BrushTexture,
     450        Matrix,
    449451        NumUniforms
    450452    };
     
    456458    };
    457459
    458     // There are optimisations we can do, depending on the brush transform:
     460    // There are optimizations we can do, depending on the brush transform:
    459461    //    1) May not have to apply perspective-correction
    460462    //    2) Can use lower precision for matrix
     
    475477    void useSimpleProgram();
    476478    void useBlitProgram();
     479    void setHasComplexGeometry(bool hasComplexGeometry)
     480    {
     481        complexGeometry = hasComplexGeometry;
     482        shaderProgNeedsChanging = true;
     483    }
     484    bool hasComplexGeometry() const
     485    {
     486        return complexGeometry;
     487    }
    477488
    478489    QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
     
    488499    QGLContext*     ctx;
    489500    bool            shaderProgNeedsChanging;
     501    bool            complexGeometry;
    490502
    491503    // Current state variables which influence the choice of shader:
  • trunk/src/opengl/gl2paintengineex/qglengineshadersource_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    107107        gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
    108108    }\n";
     109
     110static 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";
    109117
    110118static const char* const qglslUntransformedPositionVertexShader = "\n\
     
    275283    uniform   highp   vec2      invertedTextureSize; \n\
    276284    uniform   highp   mat3      brushTransform; \n\
    277     varying   highp   vec2      textureCoords; \n\
     285    varying   highp   vec2      brushTextureCoords; \n\
    278286    void setPosition(void) \n\
    279287    { \n\
     
    285293        mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
    286294        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\
    288296    }\n";
    289297
     
    296304// TODO: Special case POT textures which don't need this emulation
    297305static const char* const qglslTextureBrushSrcFragmentShader = "\n\
    298     varying highp   vec2      textureCoords; \n\
     306    varying highp   vec2      brushTextureCoords; \n\
    299307    uniform lowp    sampler2D brushTexture; \n\
    300308    lowp vec4 srcPixel() { \n\
    301         return texture2D(brushTexture, fract(textureCoords)); \n\
     309        return texture2D(brushTexture, fract(brushTextureCoords)); \n\
    302310    }\n";
    303311#else
    304312static const char* const qglslTextureBrushSrcFragmentShader = "\n\
    305     varying   highp   vec2      textureCoords; \n\
     313    varying   highp   vec2      brushTextureCoords; \n\
    306314    uniform   lowp    sampler2D brushTexture; \n\
    307315    lowp vec4 srcPixel() \n\
    308316    { \n\
    309         return texture2D(brushTexture, textureCoords); \n\
     317        return texture2D(brushTexture, brushTextureCoords); \n\
    310318    }\n";
    311319#endif
    312320
    313321static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\n\
    314     varying   highp   vec2      textureCoords; \n\
     322    varying   highp   vec2      brushTextureCoords; \n\
    315323    uniform   lowp    vec4      patternColor; \n\
    316324    uniform   lowp    sampler2D brushTexture; \n\
    317325    lowp vec4 srcPixel() \n\
    318326    { \n\
    319         return patternColor * (1.0 - texture2D(brushTexture, textureCoords).r); \n\
     327        return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\
    320328    }\n";
    321329
     
    333341    lowp vec4 srcPixel() \n\
    334342    { \n"
    335 #ifdef QT_OPENGL_ES_2
    336         // work-around for driver bug
    337         "return 1.0 * texture2D(imageTexture, textureCoords); \n"
    338 #else
    339343        "return texture2D(imageTexture, textureCoords); \n"
    340 #endif
    341344    "}\n";
    342345
  • trunk/src/opengl/gl2paintengineex/qglgradientcache.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4040****************************************************************************/
    4141
     42#include "qglgradientcache_p.h"
    4243#include <private/qdrawhelper_p.h>
    4344#include <private/qgl_p.h>
    4445
    45 #include "qglgradientcache_p.h"
    4646
    4747QT_BEGIN_NAMESPACE
  • trunk/src/opengl/gl2paintengineex/qglgradientcache_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565// #define QT_OPENGL_CACHE_AS_VBOS
    6666
     67#include "qglgradientcache_p.h"
    6768#include "qpaintengineex_opengl2_p.h"
    6869
     
    7879#include <private/qpixmapdata_gl_p.h>
    7980#include <private/qdatabuffer_p.h>
    80 
    81 #include "qglgradientcache_p.h"
     81#include <private/qstatictext_p.h>
     82#include <private/qtriangulator_p.h>
     83
    8284#include "qglengineshadermanager_p.h"
    8385#include "qgl2pexvertexarray_p.h"
     
    8991QT_BEGIN_NAMESPACE
    9092
    91 //#define QT_GL_NO_SCISSOR_TEST
     93#if defined(Q_OS_SYMBIAN)
     94#define QT_GL_NO_SCISSOR_TEST
     95#endif
     96
    9297#if defined(Q_WS_WIN)
    9398extern Q_GUI_EXPORT bool qt_cleartype_enabled;
    9499#endif
    95100
    96 extern QImage qt_imageForBrush(int brushStyle, bool invert);
     101#ifdef Q_WS_MAC
     102extern bool qt_applefontsmoothing_enabled;
     103#endif
     104
     105Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert);
    97106
    98107////////////////////////////////// Private Methods //////////////////////////////////////////
     
    107116        e->data = 0;
    108117        e->engine = 0;
     118    }
     119
     120    if (elementIndicesVBOId != 0) {
     121        glDeleteBuffers(1, &elementIndicesVBOId);
     122        elementIndicesVBOId = 0;
    109123    }
    110124}
     
    150164
    151165    currentBrush = brush;
     166    if (!currentBrushPixmap.isNull())
     167        currentBrushPixmap = QPixmap();
    152168    brushUniformsDirty = true; // All brushes have at least one uniform
    153169
     
    208224    }
    209225    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);
    211231
    212232        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);
    214236        updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
    215237        textureInvertedY = tex->options & QGLContext::InvertedYBindOption ? -1 : 1;
     
    366388        dy = ceilf(dy - 0.5f);
    367389    }
    368 
     390#ifndef Q_OS_SYMBIAN
    369391    if (addOffset) {
    370392        dx += 0.49f;
    371393        dy += 0.49f;
    372394    }
    373 
     395#endif
    374396    pmvMatrix[0][0] = (wfactor * transform.m11())  - transform.m13();
    375397    pmvMatrix[1][0] = (wfactor * transform.m21())  - transform.m23();
     
    389411
    390412    matrixDirty = false;
     413    matrixUniformDirty = true;
    391414
    392415    // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only
     
    507530    d->transferMode(BrushDrawingMode);
    508531
     532    d->nativePaintingActive = true;
     533
    509534    QGLContext *ctx = d->ctx;
    510535    glUseProgram(0);
     
    522547    float mv_matrix[4][4] =
    523548    {
    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()) }
    528553    };
    529554
     
    562587    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    563588    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);
    567592#ifndef QT_OPENGL_ES_2
    568593    glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib()
     
    574599    Q_D(QGL2PaintEngineEx);
    575600    d->needsSync = true;
     601    d->nativePaintingActive = false;
     602}
     603
     604void QGL2PaintEngineEx::invalidateState()
     605{
     606    Q_D(QGL2PaintEngineEx);
     607    d->needsSync = true;
     608}
     609
     610bool QGL2PaintEngineEx::isNativePaintingActive() const {
     611    Q_D(const QGL2PaintEngineEx);
     612    return d->nativePaintingActive;
    576613}
    577614
     
    586623
    587624    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);
    590628    }
    591629
     
    612650#ifdef QT_OPENGL_CACHE_AS_VBOS
    613651    GLuint vbo;
     652    GLuint ibo;
    614653#else
    615654    float *vertices;
     655    void *indices;
    616656#endif
    617657    int vertexCount;
     658    int indexCount;
    618659    GLenum primitiveType;
    619660    qreal iscale;
     
    626667    Q_ASSERT(engine->type() == QPaintEngine::OpenGL2);
    627668    static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo;
     669    if (c->ibo)
     670        d->unusedIBOSToClean << c->ibo;
    628671#else
    629672    Q_UNUSED(engine);
    630673    qFree(c->vertices);
     674    qFree(c->indices);
    631675#endif
    632676    delete c;
     
    669713            QVectorPath::CacheEntry *data = path.lookupCacheData(q);
    670714            QGL2PEVectorPathCache *cache;
     715
     716            bool updateCache = false;
    671717
    672718            if (data) {
     
    679725                        glDeleteBuffers(1, &cache->vbo);
    680726                        cache->vbo = 0;
     727                        Q_ASSERT(cache->ibo == 0);
    681728#else
    682729                        qFree(cache->vertices);
    683 #endif
    684                         cache->vertexCount = 0;
     730                        Q_ASSERT(cache->indices == 0);
     731#endif
     732                        updateCache = true;
    685733                    }
    686734                }
    687735            } else {
    688736                cache = new QGL2PEVectorPathCache;
    689                 cache->vertexCount = 0;
    690737                data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath);
     738                updateCache = true;
    691739            }
    692740
    693741            // Flatten the path at the current scale factor and fill it into the cache struct.
    694             if (!cache->vertexCount) {
     742            if (updateCache) {
    695743                vertexCoordinateArray.clear();
    696744                vertexCoordinateArray.addPath(path, inverseScale, false);
     
    698746                int floatSizeInBytes = vertexCount * 2 * sizeof(float);
    699747                cache->vertexCount = vertexCount;
     748                cache->indexCount = 0;
    700749                cache->primitiveType = GL_TRIANGLE_FAN;
    701750                cache->iscale = inverseScale;
     
    704753                glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
    705754                glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
     755                cache->ibo = 0;
    706756#else
    707757                cache->vertices = (float *) qMalloc(floatSizeInBytes);
    708758                memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes);
     759                cache->indices = 0;
    709760#endif
    710761            }
     
    722773      //        printf(" - Marking path as cachable...\n");
    723774            // 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();
    728776            vertexCoordinateArray.clear();
    729777            vertexCoordinateArray.addPath(path, inverseScale, false);
     
    733781
    734782    } 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
    750876        } 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        }
    760907    }
    761908}
     
    9391086        brushUniformsDirty = true;
    9401087        opacityUniformDirty = true;
     1088        matrixUniformDirty = true;
    9411089    }
    9421090
     
    9471095        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
    9481096        opacityUniformDirty = false;
     1097    }
     1098
     1099    if (matrixUniformDirty && shaderManager->hasComplexGeometry()) {
     1100        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Matrix),
     1101                                                         pmvMatrix);
     1102        matrixUniformDirty = false;
    9491103    }
    9501104
     
    10011155}
    10021156
    1003 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
     1157extern Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
    10041158
    10051159
     
    10491203    updateMatrix();
    10501204
     1205    QRectF clip = q->state()->matrix.inverted().mapRect(q->state()->clipEnabled
     1206                                                        ? q->state()->rectangleClip
     1207                                                        : QRectF(0, 0, width, height));
     1208
    10511209    if (penStyle == Qt::SolidLine) {
    1052         stroker.process(path, pen);
     1210        stroker.process(path, pen, clip);
    10531211
    10541212    } else { // Some sort of dash
    1055         dasher.process(path, pen);
     1213        dasher.process(path, pen, clip);
    10561214
    10571215        QVectorPath dashStroke(dasher.points(),
    10581216                               dasher.elementCount(),
    10591217                               dasher.elementTypes());
    1060         stroker.process(dashStroke, pen);
    1061     }
     1218        stroker.process(dashStroke, pen, clip);
     1219    }
     1220
     1221    if (!stroker.vertexCount())
     1222        return;
    10621223
    10631224    if (opaque) {
     
    11511312
    11521313
     1314static 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
    11531319void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
    11541320{
    11551321    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
    11561335    ensureActive();
    11571336    d->transferMode(ImageDrawingMode);
    11581337
    1159     QGLContext *ctx = d->ctx;
    11601338    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
    11611339    QGLTexture *texture =
     
    11691347
    11701348    bool isBitmap = pixmap.isQBitmap();
    1171     bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
     1349    bool isOpaque = !isBitmap && !pixmap.hasAlpha();
    11721350
    11731351    d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     
    11801358{
    11811359    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
    11821373    ensureActive();
    11831374    d->transferMode(ImageDrawingMode);
    11841375
    1185     QGLContext *ctx = d->ctx;
    11861376    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     1377
    11871378    QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
    11881379    GLuint id = texture->id;
     
    11931384}
    11941385
    1195 void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
     1386void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
    11961387{
    11971388    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
     1407bool 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
    11981413    ensureActive();
    11991414    d->transferMode(ImageDrawingMode);
     
    12101425                           state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
    12111426    d->drawTexture(dest, srcRect, size, false);
     1427    return true;
    12121428}
    12131429
     
    12461462
    12471463    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        }
    12491480        return;
    12501481    }
     
    12531484}
    12541485
    1255 void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType,
    1256                                                 const QTextItemInt &ti)
     1486namespace {
     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
     1510void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType,
     1511                                                QStaticTextItem *staticTextItem)
    12571512{
    12581513    Q_Q(QGL2PaintEngineEx);
    12591514
    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;
    12641518
    12651519    QGLTextureGlyphCache *cache =
    1266             (QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, glyphType, QTransform());
    1267 
     1520        (QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(ctx, glyphType, QTransform());
    12681521    if (!cache || cache->cacheType() != glyphType) {
    12691522        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    }
    12751554
    12761555    if (cache->width() == 0 || cache->height() == 0)
     
    12841563    GLfloat dy = 1.0 / cache->height();
    12851564
    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());
    13001642
    13011643    if (addOffset) {
     
    13631705            updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
    13641706
    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
    13671712
    13681713            shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
     
    13891734    //### TODO: Gamma correction
    13901735
    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
     1765void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
     1766                                            QPainter::PixmapFragmentHints hints)
    14001767{
    14011768    Q_D(QGL2PaintEngineEx);
    14021769    // Use fallback for extended composition modes.
    14031770    if (state()->composition_mode > QPainter::CompositionMode_Plus) {
    1404         QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
     1771        QPaintEngineEx::drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
    14051772        return;
    14061773    }
    14071774
    14081775    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
     1786void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments,
     1787                                                   int fragmentCount, const QPixmap &pixmap,
     1788                                                   QPainter::PixmapFragmentHints hints)
    14141789{
    14151790    GLfloat dx = 1.0f / pixmap.size().width();
     
    14321807    bool allOpaque = true;
    14331808
    1434     for (int i = 0; i < dataCount; ++i) {
     1809    for (int i = 0; i < fragmentCount; ++i) {
    14351810        qreal s = 0;
    14361811        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;
    14441819        QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
    14451820        QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c);
    14461821
    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;
    14651841        opacityArray << opacity << opacity << opacity << opacity << opacity << opacity;
    14661842        allOpaque &= (opacity >= 0.99f);
     
    14751851        // Flip texture y-coordinate.
    14761852        QGLPoint *data = textureCoordinateArray.data();
    1477         for (int i = 0; i < 6 * dataCount; ++i)
     1853        for (int i = 0; i < 6 * fragmentCount; ++i)
    14781854            data[i].y = 1 - data[i].y;
    14791855    }
     
    14821858
    14831859    bool isBitmap = pixmap.isQBitmap();
    1484     bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque;
     1860    bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
    14851861
    14861862    updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     
    14891865    // Setup for texture drawing
    14901866    currentBrush = noBrush;
    1491     shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
     1867    shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc
     1868                                            : QGLEngineShaderManager::ImageSrc);
    14921869    if (prepareForDraw(isOpaque))
    14931870        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
     
    14981875    }
    14991876
    1500     glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount);
     1877    glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount);
    15011878}
    15021879
     
    15231900    d->brushTextureDirty = true;
    15241901    d->brushUniformsDirty = true;
     1902    d->matrixUniformDirty = true;
    15251903    d->matrixDirty = true;
    15261904    d->compositionModeDirty = true;
     
    15601938#if defined(Q_WS_WIN)
    15611939    if (qt_cleartype_enabled)
     1940#endif
     1941#if defined(Q_WS_MAC)
     1942    if (qt_applefontsmoothing_enabled)
    15621943#endif
    15631944        d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
     
    16051986        d->unusedVBOSToClean.clear();
    16061987    }
     1988    if (!d->unusedIBOSToClean.isEmpty()) {
     1989        glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
     1990        d->unusedIBOSToClean.clear();
     1991    }
    16071992#endif
    16081993
     
    16262011        glViewport(0, 0, d->width, d->height);
    16272012        d->needsSync = false;
     2013        d->lastMaskTextureUsed = 0;
    16282014        d->shaderManager->setDirty();
    16292015        d->ctx->d_func()->syncGlState();
     
    18062192        QRectF rect(points[0], points[2]);
    18072193
    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        {
    18092199            state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect());
    18102200            d->updateClipScissorTest();
  • trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    124124    virtual void transformChanged();
    125125
    126     virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
    127126    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);
    129129    virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
    130130                           Qt::ImageConversionFlags flags = Qt::AutoColor);
     
    134134    virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
    135135
     136    virtual void drawStaticTextItem(QStaticTextItem *textItem);
     137
     138    bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
    136139
    137140    Type type() const { return OpenGL2; }
     
    149152    void endNativePainting();
    150153
     154    void invalidateState();
     155
    151156    QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype);
    152157
    153158    void setRenderTextActive(bool);
    154159
     160    bool isNativePaintingActive() const;
    155161private:
    156162    Q_DISABLE_COPY(QGL2PaintEngineEx)
    157163};
    158 
    159164
    160165class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
     
    174179            ctx(0),
    175180            useSystemClip(true),
     181            elementIndicesVBOId(0),
     182            opacityArray(0),
    176183            snapToPixelGrid(false),
    177184            addOffset(false),
    178             inverseScale(1)
     185            nativePaintingActive(false),
     186            inverseScale(1),
     187            lastMaskTextureUsed(0)
    179188    { }
    180189
     
    194203    void stroke(const QVectorPath &path, const QPen &pen);
    195204    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);
    198208
    199209    // Calls glVertexAttributePointer if the pointer has changed
     
    254264    bool brushUniformsDirty;
    255265    bool opacityUniformDirty;
     266    bool matrixUniformDirty;
    256267
    257268    bool stencilClean; // Has the stencil not been used for clipping so far?
     
    264275    const QBrush noBrush;
    265276
     277    QPixmap currentBrushPixmap;
     278
    266279    QGL2PEXVertexArray vertexCoordinateArray;
    267280    QGL2PEXVertexArray textureCoordinateArray;
     281    QVector<GLushort> elementIndices;
     282    GLuint elementIndicesVBOId;
    268283    QDataBuffer<GLfloat> opacityArray;
    269284    GLfloat staticVertexCoordinateArray[8];
     
    272287    bool snapToPixelGrid;
    273288    bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix
     289    bool nativePaintingActive;
    274290    GLfloat pmvMatrix[3][3];
    275291    GLfloat inverseScale;
    276292
    277293    GLuint lastTextureUsed;
     294    GLuint lastMaskTextureUsed;
    278295
    279296    bool needsSync;
     
    294311    QSet<QVectorPath::CacheEntry *> pathCaches;
    295312    QVector<GLuint> unusedVBOSToClean;
     313    QVector<GLuint> unusedIBOSToClean;
    296314
    297315    const GLfloat *vertexAttribPointers[3];
  • trunk/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qpaintengineex_opengl2_p.h"
    4444
     45#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
     46#include "private/qeglcontext_p.h"
     47#endif
     48
    4549QT_BEGIN_NAMESPACE
    4650
     
    5054
    5155QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
    52     : QTextureGlyphCache(type, matrix)
    53     , ctx(context)
     56    : QImageTextureGlyphCache(type, matrix)
     57    , ctx(0)
    5458    , m_width(0)
    5559    , m_height(0)
    56 {
    57     glGenFramebuffers(1, &m_fbo);
     60    , m_filterMode(Nearest)
     61{
     62    setContext(context);
     63}
     64
     65void 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
    5877    connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
    5978            SLOT(contextDestroyed(const QGLContext*)));
    6079}
    6180
    62 QGLTextureGlyphCache::~QGLTextureGlyphCache()
     81void QGLTextureGlyphCache::clear()
    6382{
    6483    if (ctx) {
    6584        QGLShareContextScope scope(ctx);
    66         glDeleteFramebuffers(1, &m_fbo);
    6785
    6886        if (m_width || m_height)
    6987            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
     102QGLTextureGlyphCache::~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();
    71112}
    72113
    73114void QGLTextureGlyphCache::createTextureData(int width, int height)
    74115{
     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
    75128    glGenTextures(1, &m_texture);
    76129    glBindTexture(GL_TEXTURE_2D, m_texture);
     
    79132    m_height = height;
    80133
    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;
    88143        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
     144    }
    89145
    90146    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    91147    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;
    92151}
    93152
    94153void QGLTextureGlyphCache::resizeTextureData(int width, int height)
    95154{
     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
    96175    // ### the QTextureGlyphCache API needs to be reworked to allow
    97176    // ### resizeTextureData to fail
    98 
    99     int oldWidth = m_width;
    100     int oldHeight = m_height;
    101 
    102     GLuint oldTexture = m_texture;
    103     createTextureData(width, height);
    104177
    105178    glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
     
    114187    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    115188    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     189    m_filterMode = Nearest;
    116190    glBindTexture(GL_TEXTURE_2D, 0);
    117191    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     
    160234    glBindTexture(GL_TEXTURE_2D, m_texture);
    161235
    162 #ifdef QT_OPENGL_ES_2
    163     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_ALPHA
    168     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 #else
    174236    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
    175 #endif
    176237
    177238    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     
    188249void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
    189250{
     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
    190266    QImage mask = textureMapForGlyph(glyph);
    191267    const int maskWidth = mask.width();
     
    218294        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
    219295    } else {
    220 #ifdef QT_OPENGL_ES2
    221         glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
    222 #else
    223296        // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
    224297        // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
     
    232305        for (int i = 0; i < maskHeight; ++i)
    233306            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
     310int QGLTextureGlyphCache::glyphPadding() const
     311{
     312    return 1;
     313}
     314
     315int QGLTextureGlyphCache::maxTextureWidth() const
     316{
     317    return ctx->d_ptr->maxTextureSize();
     318}
     319
     320int 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}
    249327QT_END_NAMESPACE
  • trunk/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363class QGL2PaintEngineExPrivate;
    6464
    65 class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache
     65class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QObject, public QImageTextureGlyphCache
    6666{
    6767    Q_OBJECT
     
    7373    virtual void resizeTextureData(int width, int height);
    7474    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;
    7678
    7779    inline GLuint texture() const { return m_texture; }
     
    8284    inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
    8385
     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; }
    8495
    8596public Q_SLOTS:
     
    91102                // destroy the fbo and texture here, but since the context
    92103                // 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.
    94107                m_fbo = 0;
    95108                m_texture = 0;
    96109                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();
    97118            } else {
    98119                // since the context holding the texture is shared, and
     
    103124        }
    104125    }
     126
     127    void clear();
    105128
    106129private:
     
    116139
    117140    QGLShaderProgram *m_program;
     141
     142    FilterMode m_filterMode;
    118143};
    119144
  • trunk/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7474
    7575
    76 void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen)
     76void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &)
    7777{
    7878    const qreal *pts = path.points();
     
    112112    //
    113113    // The curvyness value of PI/14 was based on,
    114     // arcLength=2*PI*r/4=PI/2 and splitting length into somewhere
     114    // arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere
    115115    // between 3 and 8 where 5 seemed to be give pretty good results
    116116    // hence: Q_PI/14. Lower divisors will give more detail at the
     
    482482
    483483QDashedStrokeProcessor::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)
    485486{
    486487    m_dash_stroker.setMoveToHook(qdashprocessor_moveTo);
     
    489490}
    490491
    491 void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen)
     492void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, const QRectF &clip)
    492493{
    493494
     
    496497    int count = path.elementCount();
    497498
     499    bool cosmetic = pen.isCosmetic();
     500
    498501    m_points.reset();
    499502    m_types.reset();
     503    m_points.reserve(path.elementCount());
     504    m_types.reserve(path.elementCount());
    500505
    501506    qreal width = qpen_widthf(pen);
     
    504509
    505510    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());
    507513    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    }
    509532
    510533    if (count < 2)
     
    541564                                                *(((const QPointF *) pts) + 2));
    542565                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);
    544568                if (threshold < 4)
    545569                    threshold = 4;
     570
    546571                qreal threshold_minus_1 = threshold - 1;
    547572                for (int i=0; i<threshold; ++i) {
  • trunk/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555{
    5656public:
    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);
    5859
    5960    inline int vertexCount() const { return m_vertices.size(); }
     
    9798    QDashedStrokeProcessor();
    9899
    99     void process(const QVectorPath &path, const QPen &pen);
     100    void process(const QVectorPath &path, const QPen &pen, const QRectF &clip);
    100101
    101102    inline void addElement(QPainterPath::ElementType type, qreal x, qreal y) {
  • trunk/src/opengl/opengl.pro

    r651 r846  
    66win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x63000000
    77solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
     8irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused
    89
    910unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui
     
    1112include(../qbase.pri)
    1213
    13 !win32:!embedded:!mac:CONFIG       += x11
     14!win32:!embedded:!mac:!symbian:CONFIG      += x11
    1415contains(QT_CONFIG, opengl):CONFIG += opengl
    1516contains(QT_CONFIG, opengles1):CONFIG += opengles1
    16 contains(QT_CONFIG, opengles1cl):CONFIG += opengles1cl
    1717contains(QT_CONFIG, opengles2):CONFIG += opengles2
    1818contains(QT_CONFIG, egl):CONFIG += egl
    1919
    2020HEADERS += qgl.h \
    21            qgl_p.h \
    22            qglcolormap.h \
    23            qglpixelbuffer.h \
     21           qgl_p.h \
     22           qglcolormap.h \
     23           qglpixelbuffer.h \
    2424           qglpixelbuffer_p.h \
    25            qglframebufferobject.h  \
     25           qglframebufferobject.h  \
    2626           qglframebufferobject_p.h  \
    2727           qglextensions_p.h \
    2828           qglpaintdevice_p.h \
     29           qglbuffer.h \
    2930
    3031
    3132SOURCES += qgl.cpp \
    32            qglcolormap.cpp \
    33            qglpixelbuffer.cpp \
    34            qglframebufferobject.cpp \
     33           qglcolormap.cpp \
     34           qglpixelbuffer.cpp \
     35           qglframebufferobject.cpp \
    3536           qglextensions.cpp \
    3637           qglpaintdevice.cpp \
     38           qglbuffer.cpp \
    3739
    3840
     
    4244}
    4345
    44 !contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles1cl) {
     46!contains(QT_CONFIG, opengles1) {
    4547    HEADERS +=  qglshaderprogram.h \
    4648                qglpixmapfilter_p.h  \
     
    5658                gl2paintengineex/qglcustomshaderstage_p.h \
    5759                gl2paintengineex/qtriangulatingstroker_p.h \
     60                gl2paintengineex/qtriangulator_p.h \
    5861                gl2paintengineex/qtextureglyphcache_gl_p.h
    5962
     
    7073                gl2paintengineex/qglcustomshaderstage.cpp \
    7174                gl2paintengineex/qtriangulatingstroker.cpp \
     75                gl2paintengineex/qtriangulator.cpp \
    7276                gl2paintengineex/qtextureglyphcache_gl.cpp
    7377
     
    7579
    7680x11 {
    77     contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles1cl)|contains(QT_CONFIG, opengles2) {
     81    contains(QT_CONFIG, egl) {
    7882        SOURCES +=  qgl_x11egl.cpp \
    7983                    qglpixelbuffer_egl.cpp \
     
    114118}
    115119win32:!wince*: {
     120    DEFINES += QT_NO_EGL
    116121    SOURCES += qgl_win.cpp \
    117                qglpixelbuffer_win.cpp
     122                   qglpixelbuffer_win.cpp
    118123}
    119124wince*: {
     
    122127               qgl_egl.cpp
    123128
    124     HEADERS += qgl_cl_p.h \
    125                qgl_egl_p.h \
     129    HEADERS += qgl_egl_p.h
    126130}
    127131
     
    144148}
    145149
     150symbian {
     151    SOURCES += qgl_symbian.cpp \
     152               qglpixelbuffer_egl.cpp \
     153               qgl_egl.cpp
     154
     155    HEADERS += qgl_egl_p.h
     156
     157    symbian:TARGET.UID3 = 0x2002131A
     158}
     159
    146160INCLUDEPATH += ../3rdparty/harfbuzz/src
  • trunk/src/opengl/qgl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5050#define INT32 dummy_INT32
    5151#define INT8 dummy_INT8
    52 #if !defined(QT_OPENGL_ES)
     52#ifdef QT_NO_EGL
    5353# include <GL/glx.h>
    5454#endif
     
    6868#include "qgl_p.h"
    6969
    70 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     70#if !defined(QT_OPENGL_ES_1)
    7171#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
    7272#endif
     
    9292#include "qfile.h"
    9393#include "qlibrary.h"
     94#include <qmutex.h>
    9495
    9596
    9697QT_BEGIN_NAMESPACE
    9798
    98 #ifdef QT_OPENGL_ES_1_CL
    99 #include "qgl_cl_p.h"
    100 #endif
    101 
    102 
    103 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
     99#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
    104100QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
    105101#endif
     
    132128QGLSignalProxy *QGLSignalProxy::instance()
    133129{
    134     return theSignalProxy();
     130    QGLSignalProxy *proxy = theSignalProxy();
     131    if (proxy && proxy->thread() != qApp->thread()) {
     132        if (proxy->thread() == QThread::currentThread())
     133            proxy->moveToThread(qApp->thread());
     134    }
     135    return proxy;
    135136}
    136137
     
    227228    \value HasOverlay        Enables the use of an overlay.
    228229    \value SampleBuffers     Enables the use of sample buffers.
     230    \value DeprecatedFunctions      Enables the use of deprecated functionality for OpenGL 3.x
     231                                    contexts. A context with deprecated functionality enabled is
     232                                    called a full context in the OpenGL specification.
    229233    \value SingleBuffer      Specifies the use of a single buffer, as opposed to double buffers.
    230234    \value NoDepthBuffer     Disables the use of a depth buffer.
     
    237241    \value NoOverlay         Disables the use of an overlay.
    238242    \value NoSampleBuffers   Disables the use of sample buffers.
     243    \value NoDeprecatedFunctions    Disables the use of deprecated functionality for OpenGL 3.x
     244                                    contexts. A context with deprecated functionality disabled is
     245                                    called a forward compatible context in the OpenGL specification.
    239246
    240247    \sa {Sample Buffers Example}
     
    508515    flicker-free drawing and often better performance.
    509516
     517    Note that single buffered contexts are currently not supported
     518    with EGL.
     519
    510520    \sa doubleBuffer(), QGLContext::swapBuffers(),
    511521    QGLWidget::swapBuffers()
     
    766776    }
    767777    d->numSamples = numSamples;
     778    setSampleBuffers(numSamples > 0);
    768779}
    769780
     
    904915    }
    905916    d->depthSize = size;
     917    setDepth(size > 0);
    906918}
    907919
     
    10171029    }
    10181030    d->alphaSize = size;
    1019     setOption(QGL::AlphaChannel);
     1031    setAlpha(size > 0);
    10201032}
    10211033
     
    10441056    }
    10451057    d->accumSize = size;
     1058    setAccum(size > 0);
    10461059}
    10471060
     
    10691082    }
    10701083    d->stencilSize = size;
     1084    setStencil(size > 0);
    10711085}
    10721086
     
    10801094   return d->stencilSize;
    10811095}
     1096
     1097/*!
     1098    \since 4.7
     1099
     1100    Set the OpenGL version to the \a major and \a minor numbers. If a
     1101    context compatible with the requested OpenGL version cannot be
     1102    created, a context compatible with version 1.x is created instead.
     1103
     1104    \sa majorVersion(), minorVersion()
     1105*/
     1106void QGLFormat::setVersion(int major, int minor)
     1107{
     1108    if (major < 1 || minor < 0) {
     1109        qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
     1110        return;
     1111    }
     1112    detach();
     1113    d->majorVersion = major;
     1114    d->minorVersion = minor;
     1115}
     1116
     1117/*!
     1118    \since 4.7
     1119
     1120    Returns the OpenGL major version.
     1121
     1122    \sa setVersion(), minorVersion()
     1123*/
     1124int QGLFormat::majorVersion() const
     1125{
     1126    return d->majorVersion;
     1127}
     1128
     1129/*!
     1130    \since 4.7
     1131
     1132    Returns the OpenGL minor version.
     1133
     1134    \sa setVersion(), majorVersion()
     1135*/
     1136int QGLFormat::minorVersion() const
     1137{
     1138    return d->minorVersion;
     1139}
     1140
     1141/*!
     1142    \enum QGLFormat::OpenGLContextProfile
     1143    \since 4.7
     1144
     1145    This enum describes the OpenGL context profiles that can be
     1146    specified for contexts implementing OpenGL version 3.2 or
     1147    higher. These profiles are different from OpenGL ES profiles.
     1148
     1149    \value NoProfile            OpenGL version is lower than 3.2.
     1150    \value CoreProfile          Functionality deprecated in OpenGL version 3.0 is not available.
     1151    \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
     1152*/
     1153
     1154/*!
     1155    \since 4.7
     1156
     1157    Set the OpenGL context profile to \a profile. The \a profile is
     1158    ignored if the requested OpenGL version is less than 3.2.
     1159
     1160    \sa profile()
     1161*/
     1162void QGLFormat::setProfile(OpenGLContextProfile profile)
     1163{
     1164    detach();
     1165    d->profile = profile;
     1166}
     1167
     1168/*!
     1169    \since 4.7
     1170
     1171    Returns the OpenGL context profile.
     1172
     1173    \sa setProfile()
     1174*/
     1175QGLFormat::OpenGLContextProfile QGLFormat::profile() const
     1176{
     1177    return d->profile;
     1178}
     1179
    10821180
    10831181/*!
     
    11171215                        versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
    11181216                                        QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
    1119                 }
    1120                 else {
     1217                } else {
    11211218                    // Not -CM, must be CL, CommonLite
    11221219                    versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
     
    11241221                        versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
    11251222                }
    1126             }
    1127             else {
     1223            } else {
    11281224                // OpenGL ES version 2.0 or higher
    11291225                versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
    11301226            }
    1131         }
    1132         else {
     1227        } else {
    11331228            // if < 3 parts to the name, it is an unrecognised OpenGL ES
    11341229            qWarning("Unrecognised OpenGL ES version");
    11351230        }
    1136     }
    1137     else {
     1231    } else {
    11381232        // not ES, regular OpenGL, the version numbers are first in the string
    11391233        if (versionString.startsWith(QLatin1String("1."))) {
     
    11521246                break;
    11531247            }
    1154         }
    1155         else if (versionString.startsWith(QLatin1String("2."))) {
     1248        } else if (versionString.startsWith(QLatin1String("2."))) {
    11561249            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
    11571250                            QGLFormat::OpenGL_Version_1_2 |
     
    11601253                            QGLFormat::OpenGL_Version_1_5 |
    11611254                            QGLFormat::OpenGL_Version_2_0;
    1162             QString minorVersion = versionString.section(QLatin1Char(' '), 0, 0).section(QLatin1Char('.'), 1, 1);
    1163             if (minorVersion == QChar(QLatin1Char('1')))
     1255            if (versionString[2].toAscii() == '1')
    11641256                versionFlags |= QGLFormat::OpenGL_Version_2_1;
     1257        } else if (versionString.startsWith(QLatin1String("3."))) {
     1258            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
     1259                            QGLFormat::OpenGL_Version_1_2 |
     1260                            QGLFormat::OpenGL_Version_1_3 |
     1261                            QGLFormat::OpenGL_Version_1_4 |
     1262                            QGLFormat::OpenGL_Version_1_5 |
     1263                            QGLFormat::OpenGL_Version_2_0 |
     1264                            QGLFormat::OpenGL_Version_2_1 |
     1265                            QGLFormat::OpenGL_Version_3_0;
     1266            switch (versionString[2].toAscii()) {
     1267            case '3':
     1268                versionFlags |= QGLFormat::OpenGL_Version_3_3;
     1269            case '2':
     1270                versionFlags |= QGLFormat::OpenGL_Version_3_2;
     1271            case '1':
     1272                versionFlags |= QGLFormat::OpenGL_Version_3_1;
     1273            case '0':
     1274                break;
     1275            default:
     1276                versionFlags |= QGLFormat::OpenGL_Version_3_1 |
     1277                                QGLFormat::OpenGL_Version_3_2 |
     1278                                QGLFormat::OpenGL_Version_3_3;
     1279                break;
     1280            }
     1281        } else if (versionString.startsWith(QLatin1String("4."))) {
     1282            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
     1283                            QGLFormat::OpenGL_Version_1_2 |
     1284                            QGLFormat::OpenGL_Version_1_3 |
     1285                            QGLFormat::OpenGL_Version_1_4 |
     1286                            QGLFormat::OpenGL_Version_1_5 |
     1287                            QGLFormat::OpenGL_Version_2_0 |
     1288                            QGLFormat::OpenGL_Version_2_1 |
     1289                            QGLFormat::OpenGL_Version_3_0 |
     1290                            QGLFormat::OpenGL_Version_3_1 |
     1291                            QGLFormat::OpenGL_Version_3_2 |
     1292                            QGLFormat::OpenGL_Version_3_3 |
     1293                            QGLFormat::OpenGL_Version_4_0;
     1294        } else {
     1295            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
     1296                            QGLFormat::OpenGL_Version_1_2 |
     1297                            QGLFormat::OpenGL_Version_1_3 |
     1298                            QGLFormat::OpenGL_Version_1_4 |
     1299                            QGLFormat::OpenGL_Version_1_5 |
     1300                            QGLFormat::OpenGL_Version_2_0 |
     1301                            QGLFormat::OpenGL_Version_2_1 |
     1302                            QGLFormat::OpenGL_Version_3_0 |
     1303                            QGLFormat::OpenGL_Version_3_1 |
     1304                            QGLFormat::OpenGL_Version_3_2 |
     1305                            QGLFormat::OpenGL_Version_3_3 |
     1306                            QGLFormat::OpenGL_Version_4_0;
    11651307        }
    1166         else if (versionString.startsWith(QLatin1String("3."))) {
    1167          versionFlags |= QGLFormat::OpenGL_Version_1_1 |
    1168                          QGLFormat::OpenGL_Version_1_2 |
    1169                          QGLFormat::OpenGL_Version_1_3 |
    1170                          QGLFormat::OpenGL_Version_1_4 |
    1171                          QGLFormat::OpenGL_Version_1_5 |
    1172                          QGLFormat::OpenGL_Version_2_0 |
    1173                          QGLFormat::OpenGL_Version_2_1 |
    1174                          QGLFormat::OpenGL_Version_3_0;
    1175         }
    1176         else
    1177             qWarning("Unrecognised OpenGL version");
    11781308    }
    11791309    return versionFlags;
     
    12061336
    12071337    \value OpenGL_Version_3_0  OpenGL version 3.0 or higher is present.
     1338
     1339    \value OpenGL_Version_3_1  OpenGL version 3.1 or higher is present.
     1340    Note that OpenGL version 3.1 or higher does not necessarily support all the features of
     1341    version 3.0 and lower.
     1342
     1343    \value OpenGL_Version_3_2  OpenGL version 3.2 or higher is present.
     1344
     1345    \value OpenGL_Version_3_3  OpenGL version 3.3 or higher is present.
     1346
     1347    \value OpenGL_Version_4_0  OpenGL version 4.0 or higher is present.
    12081348
    12091349    \value OpenGL_ES_CommonLite_Version_1_0  OpenGL ES version 1.0 Common Lite or higher is present.
     
    13781518bool operator==(const QGLFormat& a, const QGLFormat& b)
    13791519{
    1380     return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize
    1381         && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize
     1520    return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
     1521        && a.d->pln == b.d->pln
     1522        && a.d->alphaSize == b.d->alphaSize
     1523        && a.d->accumSize == b.d->accumSize
     1524        && a.d->stencilSize == b.d->stencilSize
    13821525        && a.d->depthSize == b.d->depthSize
    13831526        && a.d->redSize == b.d->redSize
     
    13851528        && a.d->blueSize == b.d->blueSize
    13861529        && a.d->numSamples == b.d->numSamples
    1387         && a.d->swapInterval == b.d->swapInterval;
    1388 }
     1530        && a.d->swapInterval == b.d->swapInterval
     1531        && a.d->majorVersion == b.d->majorVersion
     1532        && a.d->minorVersion == b.d->minorVersion
     1533        && a.d->profile == b.d->profile);
     1534}
     1535
     1536#ifndef QT_NO_DEBUG_STREAM
     1537QDebug operator<<(QDebug dbg, const QGLFormat &f)
     1538{
     1539    const QGLFormatPrivate * const d = f.d;
     1540
     1541    dbg.nospace() << "QGLFormat("
     1542                  << "options " << d->opts
     1543                  << ", plane " << d->pln
     1544                  << ", depthBufferSize " << d->depthSize
     1545                  << ", accumBufferSize " << d->accumSize
     1546                  << ", stencilBufferSize " << d->stencilSize
     1547                  << ", redBufferSize " << d->redSize
     1548                  << ", greenBufferSize " << d->greenSize
     1549                  << ", blueBufferSize " << d->blueSize
     1550                  << ", alphaBufferSize " << d->alphaSize
     1551                  << ", samples " << d->numSamples
     1552                  << ", swapInterval " << d->swapInterval
     1553                  << ", majorVersion " << d->majorVersion
     1554                  << ", minorVersion " << d->minorVersion
     1555                  << ", profile " << d->profile
     1556                  << ')';
     1557
     1558    return dbg.space();
     1559}
     1560#endif
    13891561
    13901562
     
    14001572    return !(a == b);
    14011573}
     1574
     1575struct QGLContextGroupList {
     1576    void append(QGLContextGroup *group) {
     1577        QMutexLocker locker(&m_mutex);
     1578        m_list.append(group);
     1579    }
     1580
     1581    void remove(QGLContextGroup *group) {
     1582        QMutexLocker locker(&m_mutex);
     1583        m_list.removeOne(group);
     1584    }
     1585
     1586    QList<QGLContextGroup *> m_list;
     1587    QMutex m_mutex;
     1588};
     1589
     1590Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
    14021591
    14031592/*****************************************************************************
    14041593  QGLContext implementation
    14051594 *****************************************************************************/
     1595
     1596QGLContextGroup::QGLContextGroup(const QGLContext *context)
     1597    : m_context(context), m_guards(0), m_refs(1)
     1598{
     1599    qt_context_groups()->append(this);
     1600}
    14061601
    14071602QGLContextGroup::~QGLContextGroup()
     
    14141609        guard = guard->m_next;
    14151610    }
     1611    qt_context_groups()->remove(this);
    14161612}
    14171613
     
    14471643}
    14481644
     1645QGLContextPrivate::QGLContextPrivate(QGLContext *context)
     1646    : internal_context(false)
     1647    , q_ptr(context)
     1648{
     1649    group = new QGLContextGroup(context);
     1650    texture_destroyer = new QGLTextureDestroyer;
     1651    texture_destroyer->moveToThread(qApp->thread());
     1652}
     1653
    14491654QGLContextPrivate::~QGLContextPrivate()
    14501655{
     
    14531658        delete group;
    14541659    }
     1660
     1661    delete texture_destroyer;
    14551662}
    14561663
     
    14811688    vi = 0;
    14821689#endif
    1483 #if defined(QT_OPENGL_ES)
     1690#ifndef QT_NO_EGL
     1691    ownsEglContext = false;
    14841692    eglContext = 0;
    14851693    eglSurface = EGL_NO_SURFACE;
     
    14971705    default_fbo = 0;
    14981706    active_engine = 0;
     1707    workaround_needsFullClearOnEveryFrame = false;
     1708    workaround_brokenFBOReadBack = false;
     1709    workaround_brokenTexSubImage = false;
     1710    workaroundsCached = false;
     1711
     1712    workaround_brokenTextureFromPixmap = false;
     1713    workaround_brokenTextureFromPixmap_init = false;
     1714
    14991715    for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
    15001716        vertexAttributeArraysEnabledState[i] = false;
     
    15671783    int w = size.width();
    15681784    int h = size.height();
    1569 #if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     1785#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1)
    15701786    //### glGetTexImage not in GL ES 2.0, need to do something else here!
    15711787    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
     
    15951811extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
    15961812
    1597 static QGLTextureCache *qt_gl_texture_cache = 0;
     1813
     1814Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
    15981815
    15991816QGLTextureCache::QGLTextureCache()
    16001817    : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
    16011818{
    1602     Q_ASSERT(qt_gl_texture_cache == 0);
    1603     qt_gl_texture_cache = this;
    1604 
    16051819    QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData);
    16061820    QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
     
    16101824QGLTextureCache::~QGLTextureCache()
    16111825{
    1612     qt_gl_texture_cache = 0;
    1613 
    16141826    QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
    16151827    QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
     
    16191831void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
    16201832{
     1833    QWriteLocker locker(&m_lock);
    16211834    if (m_cache.totalCost() + cost > m_cache.maxCost()) {
    16221835        // the cache is full - make an attempt to remove something
    1623         const QList<qint64> keys = m_cache.keys();
     1836        const QList<QGLTextureCacheKey> keys = m_cache.keys();
    16241837        int i = 0;
    16251838        while (i < m_cache.count()
     
    16311844        }
    16321845    }
    1633     m_cache.insert(key, texture, cost);
     1846    const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
     1847    m_cache.insert(cacheKey, texture, cost);
     1848}
     1849
     1850void QGLTextureCache::remove(qint64 key)
     1851{
     1852    QWriteLocker locker(&m_lock);
     1853    QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
     1854    QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
     1855    while (it != qt_context_groups()->m_list.constEnd()) {
     1856        const QGLTextureCacheKey cacheKey = {key, *it};
     1857        m_cache.remove(cacheKey);
     1858        ++it;
     1859    }
    16341860}
    16351861
    16361862bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
    16371863{
    1638     QList<qint64> keys = m_cache.keys();
     1864    QWriteLocker locker(&m_lock);
     1865    QList<QGLTextureCacheKey> keys = m_cache.keys();
    16391866    for (int i = 0; i < keys.size(); ++i) {
    16401867        QGLTexture *tex = m_cache.object(keys.at(i));
     
    16501877void QGLTextureCache::removeContextTextures(QGLContext* ctx)
    16511878{
    1652     QList<qint64> keys = m_cache.keys();
     1879    QWriteLocker locker(&m_lock);
     1880    QList<QGLTextureCacheKey> keys = m_cache.keys();
    16531881    for (int i = 0; i < keys.size(); ++i) {
    1654         const qint64 &key = keys.at(i);
     1882        const QGLTextureCacheKey &key = keys.at(i);
    16551883        if (m_cache.object(key)->context == ctx)
    16561884            m_cache.remove(key);
    16571885    }
    1658 }
    1659 
    1660 QGLTextureCache* QGLTextureCache::instance()
    1661 {
    1662     if (!qt_gl_texture_cache)
    1663         qt_gl_texture_cache = new QGLTextureCache;
    1664 
    1665     return qt_gl_texture_cache;
    16661886}
    16671887
     
    16721892void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
    16731893{
    1674     // ### remove when the GL texture cache becomes thread-safe
    1675     if (qApp->thread() == QThread::currentThread()) {
    1676         instance()->remove(cacheKey);
    1677         Q_ASSERT(instance()->getTexture(cacheKey) == 0);
    1678     }
     1894    qt_gl_texture_cache()->remove(cacheKey);
    16791895}
    16801896
     
    16981914}
    16991915
    1700 void QGLTextureCache::deleteIfEmpty()
    1701 {
    1702     if (instance()->size() == 0)
    1703         delete instance();
     1916QGLTextureCache *QGLTextureCache::instance()
     1917{
     1918    return qt_gl_texture_cache();
    17041919}
    17051920
     
    18012016
    18022017    \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
    1803     wether or not it can bind the pixmap upside down or not.
     2018    whether or not it can bind the pixmap upside down or not.
    18042019
    18052020    \omitvalue MemoryManagedBindOption Used by paint engines to
     
    18672082    // remove any textures cached in this context
    18682083    QGLTextureCache::instance()->removeContextTextures(this);
    1869     QGLTextureCache::deleteIfEmpty(); // ### thread safety
    18702084
    18712085    d_ptr->group->cleanupResources(this);
     
    18832097{
    18842098    Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
     2099#ifdef glEnableVertexAttribArray
    18852100    Q_ASSERT(glEnableVertexAttribArray);
     2101#endif
    18862102
    18872103    if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
     
    18962112void QGLContextPrivate::syncGlState()
    18972113{
     2114#ifdef glEnableVertexAttribArray
    18982115    Q_ASSERT(glEnableVertexAttribArray);
     2116#endif
    18992117    for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
    19002118        if (vertexAttributeArraysEnabledState[i])
     
    19072125#undef ctx
    19082126
     2127#ifdef QT_NO_EGL
     2128void QGLContextPrivate::swapRegion(const QRegion &)
     2129{
     2130    Q_Q(QGLContext);
     2131    q->swapBuffers();
     2132}
     2133#endif
    19092134
    19102135/*!
     
    20612286}
    20622287
     2288#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
     2289QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
     2290{
     2291    return qt_extensionFuncs;
     2292}
     2293#endif
     2294
    20632295QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
    20642296                                            GLenum texture_format)
     
    20772309                                           QGLContext::BindOptions options)
    20782310{
     2311    Q_Q(QGLContext);
     2312
    20792313    const qint64 key = image.cacheKey();
    20802314    QGLTexture *texture = textureCacheLookup(key, target);
    20812315    if (texture) {
    2082         glBindTexture(target, texture->id);
    2083         return texture;
     2316        if (image.paintingActive()) {
     2317            // A QPainter is active on the image - take the safe route and replace the texture.
     2318            q->deleteTexture(texture->id);
     2319            texture = 0;
     2320        } else {
     2321            glBindTexture(target, texture->id);
     2322            return texture;
     2323        }
    20842324    }
    20852325
     
    21272367
    21282368#ifdef QGL_BIND_TEXTURE_DEBUG
    2129     printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x\n",
    2130            image.width(), image.height(), internalFormat, int(options));
     2369    printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
     2370           image.width(), image.height(), internalFormat, int(options), key);
    21312371    QTime time;
    21322372    time.start();
     
    21722412        && (options & QGLContext::MipmapBindOption))
    21732413    {
    2174 #ifdef QGL_BIND_TEXTURE_DEBUG
    2175         printf(" - generating mipmaps (%d ms)\n", time.elapsed());
    2176 #endif
    21772414#if !defined(QT_OPENGL_ES_2)
    21782415        glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
     
    21882425        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
    21892426                        ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
     2427#ifdef QGL_BIND_TEXTURE_DEBUG
     2428        printf(" - generating mipmaps (%d ms)\n", time.elapsed());
     2429#endif
    21902430    } else {
    21912431        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
     
    22122452            img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
    22132453#ifdef QGL_BIND_TEXTURE_DEBUG
    2214             printf(" - converting ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
     2454            printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
    22152455#endif
    22162456        }
     
    22202460            img = img.convertToFormat(target_format = QImage::Format_ARGB32);
    22212461#ifdef QGL_BIND_TEXTURE_DEBUG
    2222             printf(" - converting ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
     2462            printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
    22232463#endif
    22242464        }
     
    22372477                                      : QImage::Format_ARGB32);
    22382478#ifdef QGL_BIND_TEXTURE_DEBUG
    2239             printf(" - converting to 32-bit alpha format (%d ms)\n", time.elapsed());
     2479            printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
    22402480#endif
    22412481        } else {
    22422482            img = img.convertToFormat(QImage::Format_RGB32);
    22432483#ifdef QGL_BIND_TEXTURE_DEBUG
    2244             printf(" - converting to 32-bit (%d ms)\n", time.elapsed());
     2484            printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
    22452485#endif
    22462486        }
     
    22482488
    22492489    if (options & QGLContext::InvertedYBindOption) {
    2250 #ifdef QGL_BIND_TEXTURE_DEBUG
    2251             printf(" - flipping bits over y (%d ms)\n", time.elapsed());
    2252 #endif
    22532490        if (img.isDetached()) {
    22542491            int ipl = img.bytesPerLine() / 4;
     
    22672504            img = img.mirrored();
    22682505        }
     2506#ifdef QGL_BIND_TEXTURE_DEBUG
     2507            printf(" - flipped bits over y (%d ms)\n", time.elapsed());
     2508#endif
    22692509    }
    22702510
    22712511    if (externalFormat == GL_RGBA) {
    2272 #ifdef QGL_BIND_TEXTURE_DEBUG
    2273             printf(" - doing byte swapping (%d ms)\n", time.elapsed());
    2274 #endif
    22752512        // The only case where we end up with a depth different from
    22762513        // 32 in the switch above is for the RGB16 case, where we set
     
    22782515        Q_ASSERT(img.depth() == 32);
    22792516        qgl_byteSwapImage(img, pixel_type);
     2517#ifdef QGL_BIND_TEXTURE_DEBUG
     2518            printf(" - did byte swapping (%d ms)\n", time.elapsed());
     2519#endif
    22802520    }
    22812521#ifdef QT_OPENGL_ES
     
    22992539    GLenum error = glGetError();
    23002540    if (error != GL_NO_ERROR) {
    2301         qWarning(" - texture upload failed, error code 0x%x\n", error);
     2541        qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
    23022542    }
    23032543#endif
     
    23062546    static int totalUploadTime = 0;
    23072547    totalUploadTime += time.elapsed();
    2308     printf(" - upload done in (%d ms) time=%d\n", time.elapsed(), totalUploadTime);
     2548    printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
    23092549#endif
    23102550
     
    23212561{
    23222562    Q_Q(QGLContext);
    2323     QGLTexture *texture = QGLTextureCache::instance()->getTexture(key);
     2563    QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
    23242564    if (texture && texture->target == target
    23252565        && (texture->context == q || QGLContext::areSharing(q, texture->context)))
     
    23362576    Q_Q(QGLContext);
    23372577    QPixmapData *pd = pixmap.pixmapData();
    2338 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     2578#if !defined(QT_OPENGL_ES_1)
    23392579    if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
    23402580        const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
     
    23472587#else
    23482588    Q_UNUSED(pd);
    2349     Q_UNUSED(q);
    23502589#endif
    23512590
     
    23532592    QGLTexture *texture = textureCacheLookup(key, target);
    23542593    if (texture) {
    2355         glBindTexture(target, texture->id);
    2356         return texture;
     2594        if (pixmap.paintingActive()) {
     2595            // A QPainter is active on the pixmap - take the safe route and replace the texture.
     2596            q->deleteTexture(texture->id);
     2597            texture = 0;
     2598        } else {
     2599            glBindTexture(target, texture->id);
     2600            return texture;
     2601        }
    23572602    }
    23582603
     
    23612606    const QX11Info *xinfo = qt_x11Info(paintDevice);
    23622607    if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
    2363         && xinfo && xinfo->screen() == pixmap.x11Info().screen())
     2608        && xinfo && xinfo->screen() == pixmap.x11Info().screen()
     2609        && target == GL_TEXTURE_2D)
    23642610    {
    2365         texture = bindTextureFromNativePixmap(pd, key, options);
    2366         if (texture) {
    2367             texture->options |= QGLContext::MemoryManagedBindOption;
    2368             texture->boundPixmap = pd;
    2369             boundPixmaps.insert(pd, QPixmap(pixmap));
     2611        if (!workaround_brokenTextureFromPixmap_init) {
     2612            workaround_brokenTextureFromPixmap_init = true;
     2613
     2614            const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
     2615            const int pos = versionString.indexOf("NVIDIA ");
     2616
     2617            if (pos >= 0) {
     2618                const QByteArray nvidiaVersionString = versionString.mid(pos + strlen("NVIDIA "));
     2619
     2620                if (nvidiaVersionString.startsWith("195") || nvidiaVersionString.startsWith("256"))
     2621                    workaround_brokenTextureFromPixmap = true;
     2622            }
    23702623        }
    2371     }
    2372 #endif
    2373 
    2374     if (!texture)
    2375         texture = bindTexture(pixmap.toImage(), target, format, key, options);
     2624
     2625        if (!workaround_brokenTextureFromPixmap) {
     2626            texture = bindTextureFromNativePixmap(const_cast<QPixmap*>(&pixmap), key, options);
     2627            if (texture) {
     2628                texture->options |= QGLContext::MemoryManagedBindOption;
     2629                texture->boundPixmap = pd;
     2630                boundPixmaps.insert(pd, QPixmap(pixmap));
     2631            }
     2632        }
     2633    }
     2634#endif
     2635
     2636    if (!texture) {
     2637        QImage image = pixmap.toImage();
     2638        // If the system depth is 16 and the pixmap doesn't have an alpha channel
     2639        // then we convert it to RGB16 in the hope that it gets uploaded as a 16
     2640        // bit texture which is much faster to access than a 32-bit one.
     2641        if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
     2642            image = image.convertToFormat(QImage::Format_RGB16);
     2643        texture = bindTexture(image, target, format, key, options);
     2644    }
    23762645    // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
    23772646    Q_ASSERT(texture);
     
    24662735
    24672736    Q_D(QGLContext);
    2468     QGLTexture *texture = d->bindTexture(image, target, format, false, options);
     2737    QGLTexture *texture = d->bindTexture(image, target, format, options);
    24692738    return texture->id;
    24702739}
     
    24782747
    24792748    Q_D(QGLContext);
    2480     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
     2749    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), DefaultBindOption);
    24812750    return texture->id;
    24822751}
     
    24902759
    24912760    Q_D(QGLContext);
    2492     QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
     2761    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), options);
    24932762    return texture->id;
    24942763}
     
    25882857#endif
    25892858
    2590 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
     2859void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
    25912860{
    25922861    qreal left = r.left();
     
    25952864    qreal bottom = r.bottom();
    25962865
    2597     array[0] = f2vt(left);
    2598     array[1] = f2vt(top);
    2599     array[2] = f2vt(right);
    2600     array[3] = f2vt(top);
    2601     array[4] = f2vt(right);
    2602     array[5] = f2vt(bottom);
    2603     array[6] = f2vt(left);
    2604     array[7] = f2vt(bottom);
    2605 }
    2606 
    2607 void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
    2608 {
    2609     array[0] = f2vt(x1);
    2610     array[1] = f2vt(y1);
    2611     array[2] = f2vt(x2);
    2612     array[3] = f2vt(y1);
    2613     array[4] = f2vt(x2);
    2614     array[5] = f2vt(y2);
    2615     array[6] = f2vt(x1);
    2616     array[7] = f2vt(y2);
     2866    array[0] = left;
     2867    array[1] = top;
     2868    array[2] = right;
     2869    array[3] = top;
     2870    array[4] = right;
     2871    array[5] = bottom;
     2872    array[6] = left;
     2873    array[7] = bottom;
     2874}
     2875
     2876void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array)
     2877{
     2878    array[0] = x1;
     2879    array[1] = y1;
     2880    array[2] = x2;
     2881    array[3] = y1;
     2882    array[4] = x2;
     2883    array[5] = y2;
     2884    array[6] = x1;
     2885    array[7] = y2;
    26172886}
    26182887
     
    26212890static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
    26222891{
    2623     q_vertexType tx = f2vt(1);
    2624     q_vertexType ty = f2vt(1);
     2892    GLfloat tx = 1.0f;
     2893    GLfloat ty = 1.0f;
    26252894
    26262895#ifdef QT_OPENGL_ES
     
    26352904        }
    26362905
    2637         tx = f2vt(textureWidth);
    2638         ty = f2vt(textureHeight);
    2639     }
    2640 #endif
    2641 
    2642     q_vertexType texCoordArray[4*2] = {
     2906        tx = GLfloat(textureWidth);
     2907        ty = GLfloat(textureHeight);
     2908    }
     2909#endif
     2910
     2911    GLfloat texCoordArray[4*2] = {
    26432912        0, ty, tx, ty, tx, 0, 0, 0
    26442913    };
    26452914
    2646     q_vertexType vertexArray[4*2];
     2915    GLfloat vertexArray[4*2];
    26472916    qt_add_rect_to_array(target, vertexArray);
    26482917
    2649     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    2650     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     2918    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     2919    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
    26512920
    26522921    glEnableClientState(GL_VERTEX_ARRAY);
     
    26632932    \since 4.4
    26642933
    2665     Draws the given texture, \a textureId, to the given target rectangle,
    2666     \a target, in OpenGL model space. The \a textureTarget should be a 2D
    2667     texture target.
    2668 
    2669     \note This function is not supported under OpenGL/ES 2.0.
     2934    This function supports the following use cases:
     2935
     2936    \list
     2937    \i On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
     2938    to the given target rectangle, \a target, in OpenGL model space. The
     2939    \a textureTarget should be a 2D texture target.
     2940    \i On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
     2941    beginNativePainting / endNativePainting block, and uses the
     2942    engine with type QPaintEngine::OpenGL2, the function will draw the given
     2943    texture, \a textureId, to the given target rectangle, \a target,
     2944    respecting the current painter state. This will let you draw a texture
     2945    with the clip, transform, render hints, and composition mode set by the
     2946    painter. Note that the texture target needs to be GL_TEXTURE_2D for this
     2947    use case, and that this is the only supported use case under OpenGL ES 2.x.
     2948    \endlist
     2949
    26702950*/
    26712951void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
    26722952{
     2953#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
     2954     if (d_ptr->active_engine &&
     2955         d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
     2956         QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
     2957         if (!eng->isNativePaintingActive()) {
     2958            QRectF src(0, 0, target.width(), target.height());
     2959            QSize size(target.width(), target.height());
     2960            if (eng->drawTexture(target, textureId, size, src))
     2961                return;
     2962        }
     2963     }
     2964#endif
     2965
    26732966#ifndef QT_OPENGL_ES_2
    26742967#ifdef QT_OPENGL_ES
     
    26992992    Q_UNUSED(textureId);
    27002993    Q_UNUSED(textureTarget);
    2701     qWarning("drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES/2.0");
     2994    qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
    27022995#endif
    27032996}
     
    27143007    \since 4.4
    27153008
    2716     Draws the given texture at the given \a point in OpenGL model
    2717     space. The \a textureTarget should be a 2D texture target.
    2718 
    2719     \note This function is not supported under OpenGL/ES.
     3009    This function supports the following use cases:
     3010
     3011    \list
     3012    \i By default it draws the given texture, \a textureId,
     3013    at the given \a point in OpenGL model space. The
     3014    \a textureTarget should be a 2D texture target.
     3015    \i If a painter is active, not inside a
     3016    beginNativePainting / endNativePainting block, and uses the
     3017    engine with type QPaintEngine::OpenGL2, the function will draw the given
     3018    texture, \a textureId, at the given \a point,
     3019    respecting the current painter state. This will let you draw a texture
     3020    with the clip, transform, render hints, and composition mode set by the
     3021    painter. Note that the texture target needs to be GL_TEXTURE_2D for this
     3022    use case.
     3023    \endlist
     3024
     3025    \note This function is not supported under any version of OpenGL ES.
    27203026*/
    27213027void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
    27223028{
    2723     // this would be ok on OpenGL ES 2.0, but currently we don't have a define for that
    27243029#ifdef QT_OPENGL_ES
    27253030    Q_UNUSED(point);
     
    27283033    qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
    27293034#else
     3035
    27303036    const bool wasEnabled = glIsEnabled(GL_TEXTURE_2D);
    27313037    GLint oldTexture;
     
    27403046    glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
    27413047    glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
     3048
     3049    if (d_ptr->active_engine &&
     3050        d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
     3051        QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
     3052        if (!eng->isNativePaintingActive()) {
     3053            QRectF dest(point, QSizeF(textureWidth, textureHeight));
     3054            QRectF src(0, 0, textureWidth, textureHeight);
     3055            QSize size(textureWidth, textureHeight);
     3056            if (eng->drawTexture(dest, textureId, size, src))
     3057                return;
     3058        }
     3059    }
    27423060
    27433061    qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
     
    31993517    \sa QGLWidget::renderText()
    32003518*/
     3519
    32013520
    32023521
     
    33213640    \l{Overpainting Example}{Overpainting} example.
    33223641
     3642    \section1 Threading
     3643
     3644    It is possible to render into a QGLWidget from another thread, but it
     3645    requires that all access to the GL context is safe guarded. The Qt GUI
     3646    thread will try to use the context in resizeEvent and paintEvent, so in
     3647    order for threaded rendering using a GL widget to work, these functions
     3648    need to be intercepted in the GUI thread and handled accordingly in the
     3649    application.
     3650
    33233651    \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
    33243652    countries.}
     
    34483776#endif
    34493777    delete d->glcx;
    3450 #if defined(Q_WGL)
     3778    d->glcx = 0;
     3779#if defined(Q_WS_WIN)
    34513780    delete d->olcx;
     3781    d->olcx = 0;
    34523782#endif
    34533783#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
     
    38514181    }
    38524182
    3853 #if defined(QT_OPENGL_ES)
     4183#ifndef QT_NO_EGL
    38544184    // A re-parent is likely to destroy the X11 window and re-create it. It is important
    38554185    // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
     
    38604190        // The window may have been re-created during re-parent or state change - if so, the EGL
    38614191        // surface will need to be re-created.
    3862         d->recreateEglSurface(false);
     4192        d->recreateEglSurface();
    38634193    }
    38644194#endif
     
    39024232#  endif
    39034233    }
     4234#elif defined(Q_OS_SYMBIAN)
     4235    // prevents errors on some systems, where we get a flush to a
     4236    // hidden widget
     4237    if (e->type() == QEvent::Hide) {
     4238        makeCurrent();
     4239        glFinish();
     4240        doneCurrent();
     4241    } else if (e->type() == QEvent::ParentChange) {
     4242        // if we've reparented a window that has the current context
     4243        // bound, we need to rebind that context to the new window id
     4244        if (d->glcx == QGLContext::currentContext())
     4245            makeCurrent();
     4246
     4247        if (testAttribute(Qt::WA_TranslucentBackground))
     4248            setContext(new QGLContext(d->glcx->requestedFormat(), this));
     4249    }
     4250
     4251    // A re-parent is likely to destroy the Symbian window and re-create it. It is important
     4252    // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
     4253    if (e->type() == QEvent::ParentAboutToChange)
     4254        d->glcx->d_func()->destroyEglSurfaceForDevice();
     4255
     4256    if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
     4257        // The window may have been re-created during re-parent or state change - if so, the EGL
     4258        // surface will need to be re-created.
     4259        d->recreateEglSurface();
     4260    }
     4261
    39044262#endif
    39054263
     
    41094467    if (!isValid())
    41104468        return;
     4469#ifdef Q_OS_SYMBIAN
     4470    // Crashes on Symbian if trying to render to invisible surfaces
     4471    if (!isVisible() && d->glcx->device()->devType() == QInternal::Widget)
     4472        return;
     4473#endif
    41114474    makeCurrent();
    41124475#ifndef QT_OPENGL_ES
     
    47665129    \since 4.4
    47675130
    4768     Draws the given texture, \a textureId to the given target rectangle,
    4769     \a target, in OpenGL model space. The \a textureTarget should be a 2D
    4770     texture target.
    4771 
    4772     Equivalent to the corresponding QGLContext::drawTexture().
     5131    Calls the corresponding QGLContext::drawTexture() with
     5132    \a target, \a textureId, and \a textureTarget for this
     5133    widget's context.
    47735134*/
    47745135void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
     
    47905151    \since 4.4
    47915152
    4792     Draws the given texture, \a textureId, at the given \a point in OpenGL
    4793     model space. The \a textureTarget should be a 2D texture target.
    4794 
    4795     Equivalent to the corresponding QGLContext::drawTexture().
     5153    Calls the corresponding QGLContext::drawTexture() with
     5154    \a point, \a textureId, and \a textureTarget for this
     5155    widget's context.
    47965156*/
    47975157void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
     
    48105170#endif
    48115171
    4812 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     5172#ifndef QT_OPENGL_ES_1
    48135173Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
    48145174#endif
     
    48205180Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
    48215181{
    4822 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     5182#if defined(QT_OPENGL_ES_1)
    48235183    return qt_gl_engine();
    48245184#elif defined(QT_OPENGL_ES_2)
     
    49245284    if (extensions.match("GL_ARB_fragment_shader"))
    49255285        glExtensions |= FragmentShader;
     5286    if (extensions.match("GL_ARB_shader_objects"))
     5287        glExtensions |= FragmentShader;
    49265288    if (extensions.match("GL_ARB_texture_mirrored_repeat"))
    49275289        glExtensions |= MirroredRepeat;
     
    49385300    if (extensions.match("GL_ARB_pixel_buffer_object"))
    49395301        glExtensions |= PixelBufferObject;
     5302    if (extensions.match("GL_IMG_texture_format_BGRA8888"))
     5303        glExtensions |= BGRATextureFormat;
    49405304#if defined(QT_OPENGL_ES_2)
    49415305    glExtensions |= FramebufferObject;
     
    49435307    glExtensions |= FragmentShader;
    49445308#endif
    4945 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     5309#if defined(QT_OPENGL_ES_1)
    49465310    if (extensions.match("GL_OES_framebuffer_object"))
    49475311        glExtensions |= FramebufferObject;
     
    49505314    if (extensions.match("GL_OES_packed_depth_stencil"))
    49515315        glExtensions |= PackedDepthStencil;
     5316    if (extensions.match("GL_OES_element_index_uint"))
     5317        glExtensions |= ElementIndexUint;
     5318    if (extensions.match("GL_OES_depth24"))
     5319        glExtensions |= Depth24;
     5320#else
     5321    glExtensions |= ElementIndexUint;
    49525322#endif
    49535323    if (extensions.match("GL_ARB_framebuffer_object")) {
     
    49695339}
    49705340
     5341
     5342class QGLDefaultExtensions
     5343{
     5344public:
     5345    QGLDefaultExtensions() {
     5346        QGLTemporaryContext tempContext;
     5347        extensions = QGLExtensions::currentContextExtensions();
     5348    }
     5349
     5350    QGLExtensions::Extensions extensions;
     5351};
     5352
     5353Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions)
     5354
    49715355/*
    49725356    Returns the GL extensions for the current QGLContext. If there is no
     
    49765360QGLExtensions::Extensions QGLExtensions::glExtensions()
    49775361{
    4978     QGLTemporaryContext *tmpContext = 0;
    4979     static bool cachedDefault = false;
    4980     static Extensions defaultExtensions = 0;
     5362    Extensions extensionFlags = 0;
    49815363    QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
    49825364
     
    49855367
    49865368    if (!currentCtx) {
    4987         if (cachedDefault) {
    4988             return defaultExtensions;
    4989         } else {
    4990             tmpContext = new QGLTemporaryContext;
    4991             cachedDefault = true;
    4992         }
    4993     }
    4994 
    4995     Extensions extensionFlags = currentContextExtensions();
    4996     if (currentCtx) {
     5369        extensionFlags = qtDefaultExtensions()->extensions;
     5370    } else {
     5371        extensionFlags = currentContextExtensions();
    49975372        currentCtx->d_func()->extension_flags_cached = true;
    49985373        currentCtx->d_func()->extension_flags = extensionFlags;
    4999     } else {
    5000         defaultExtensions = extensionFlags;
    5001     }
    5002 
    5003     if (tmpContext)
    5004         delete tmpContext;
    5005 
     5374    }
    50065375    return extensionFlags;
    50075376}
     
    50385407{
    50395408    if (qt_gl_lib_name()->isNull()) {
    5040 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
     5409#ifdef Q_WS_MAC
     5410        return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
     5411#else
     5412# if defined(QT_OPENGL_ES_1)
     5413        return QLatin1String("GLES_CM");
     5414# elif defined(QT_OPENGL_ES_2)
     5415        return QLatin1String("GLESv2");
     5416# else
    50415417        return QLatin1String("GL");
    5042 #else // Q_WS_MAC
    5043         return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
    5044 #endif
     5418# endif
     5419#endif // defined Q_WS_MAC
    50455420    }
    50465421    return *qt_gl_lib_name();
  • trunk/src/opengl/qgl.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5858# include <OpenGL/gl.h>
    5959# include <OpenGL/glu.h>
    60 #elif defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     60#elif defined(QT_OPENGL_ES_1)
    6161# include <GLES/gl.h>
    6262#ifndef GL_DOUBLE
     
    145145        HasOverlay              = 0x0100,
    146146        SampleBuffers           = 0x0200,
     147        DeprecatedFunctions     = 0x0400,
    147148        SingleBuffer            = DoubleBuffer    << 16,
    148149        NoDepthBuffer           = DepthBuffer     << 16,
     
    154155        IndirectRendering       = DirectRendering << 16,
    155156        NoOverlay               = HasOverlay      << 16,
    156         NoSampleBuffers         = SampleBuffers   << 16
     157        NoSampleBuffers         = SampleBuffers   << 16,
     158        NoDeprecatedFunctions   = DeprecatedFunctions << 16
    157159    };
    158160    Q_DECLARE_FLAGS(FormatOptions, FormatOption)
     
    236238    static bool hasOpenGLOverlays();
    237239
    238     enum  OpenGLVersionFlag {
     240    void setVersion(int major, int minor);
     241    int majorVersion() const;
     242    int minorVersion() const;
     243
     244    enum OpenGLContextProfile {
     245        NoProfile,
     246        CoreProfile,
     247        CompatibilityProfile
     248    };
     249
     250    void setProfile(OpenGLContextProfile profile);
     251    OpenGLContextProfile profile() const;
     252
     253    enum OpenGLVersionFlag {
    239254        OpenGL_Version_None               = 0x00000000,
    240255        OpenGL_Version_1_1                = 0x00000001,
     
    250265        OpenGL_ES_CommonLite_Version_1_1  = 0x00000400,
    251266        OpenGL_ES_Version_2_0             = 0x00000800,
    252         OpenGL_Version_3_0                = 0x00001000
     267        OpenGL_Version_3_0                = 0x00001000,
     268        OpenGL_Version_3_1                = 0x00002000,
     269        OpenGL_Version_3_2                = 0x00004000,
     270        OpenGL_Version_3_3                = 0x00008000,
     271        OpenGL_Version_4_0                = 0x00010000
    253272    };
    254273    Q_DECLARE_FLAGS(OpenGLVersionFlags, OpenGLVersionFlag)
     
    263282    friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
    264283    friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
     284#ifndef QT_NO_DEBUG_STREAM
     285    friend Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
     286#endif
    265287};
    266288
     
    269291Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
    270292Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
     293
     294#ifndef QT_NO_DEBUG_STREAM
     295Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
     296#endif
    271297
    272298class Q_OPENGL_EXPORT QGLContext
     
    360386    virtual int choosePixelFormat(void* pfd, HDC pdc);
    361387#endif
    362 #if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     388#if defined(Q_WS_X11) && defined(QT_NO_EGL)
    363389    virtual void* tryVisual(const QGLFormat& f, int bufDepth = 1);
    364390    virtual void* chooseVisual();
     
    403429    friend class QGLPixmapBlurFilter;
    404430    friend class QGLExtensions;
     431    friend class QGLTexture;
    405432    friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
    406433#ifdef Q_WS_MAC
     
    415442    friend class QGLFBOGLPaintDevice;
    416443    friend class QGLPaintDevice;
     444    friend class QGLWidgetGLPaintDevice;
    417445    friend class QX11GLPixmapData;
     446    friend class QX11GLSharedContexts;
    418447private:
    419448    Q_DISABLE_COPY(QGLContext)
  • trunk/src/opengl/qgl_egl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include <QtOpenGL/qgl.h>
     43#include <QtOpenGL/qglpixelbuffer.h>
    4344#include "qgl_p.h"
    4445#include "qgl_egl_p.h"
     46#include "qglpixelbuffer_p.h"
     47
     48#ifdef Q_WS_X11
     49#include <QtGui/private/qpixmap_x11_p.h>
     50#endif
    4551
    4652QT_BEGIN_NAMESPACE
    4753
    48 // Set device configuration attributes from a QGLFormat instance.
    49 void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f)
    50 {
    51     if (deviceType == QInternal::Pixmap || deviceType == QInternal::Image)
    52         props.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
    53     else if (deviceType == QInternal::Pbuffer)
    54         props.setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
    55     else
    56         props.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
    57 
    58     // Set the pixel format to that contained in the QGLFormat
    59     // if the system hasn't already chosen a fixed format to
    60     // match the pixmap, widget, etc.
    61     if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1)
    62         props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize());
    63     if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1)
    64         props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize());
    65     if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1)
    66         props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize());
    67     if (f.alpha()) {
    68         if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1)
    69             props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize());
    70     }
    71 
    72     if (f.depth())
    73         props.setValue(EGL_DEPTH_SIZE, f.depthBufferSize() == -1 ? 1 : f.depthBufferSize());
    74     if (f.stencil())
    75         props.setValue(EGL_STENCIL_SIZE, f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize());
    76     if (f.sampleBuffers()) {
    77         props.setValue(EGL_SAMPLE_BUFFERS, 1);
    78         props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples());
    79     } else {
    80         props.setValue(EGL_SAMPLE_BUFFERS, 0);
    81     }
    82     if (deviceType == QInternal::Widget)
    83         props.setValue(EGL_LEVEL, f.plane());
     54void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat)
     55{
     56    int redSize     = glFormat.redBufferSize();
     57    int greenSize   = glFormat.greenBufferSize();
     58    int blueSize    = glFormat.blueBufferSize();
     59    int alphaSize   = glFormat.alphaBufferSize();
     60    int depthSize   = glFormat.depthBufferSize();
     61    int stencilSize = glFormat.stencilBufferSize();
     62    int sampleCount = glFormat.samples();
     63
     64    // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
     65    // type has been requested. So we must check QGLFormat's booleans too if size is -1:
     66    if (glFormat.alpha() && alphaSize <= 0)
     67        alphaSize = 1;
     68    if (glFormat.depth() && depthSize <= 0)
     69        depthSize = 1;
     70    if (glFormat.stencil() && stencilSize <= 0)
     71        stencilSize = 1;
     72    if (glFormat.sampleBuffers() && sampleCount <= 0)
     73        sampleCount = 1;
     74
     75    // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
     76    // the best performance. The EGL config selection algorithm is a bit stange in this regard:
     77    // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
     78    // 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
     79    // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
     80    // order is special and described as "by larger _total_ number of color bits.". So EGL will
     81    // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
     82    // to say "If the requested number of bits in attrib_list for a particular component is 0,
     83    // then the number of bits for that component is not considered". This part of the spec also
     84    // seems to imply that setting the red/green/blue bits to zero means none of the components
     85    // are considered and EGL disregards the entire sorting rule. It then looks to the next
     86    // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
     87    // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
     88    // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
     89    // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
     90    // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will
     91    // probably get a 32-bit config, even when there's an RGB565 config available. Oh well.
     92
     93    // Now normalize the values so -1 becomes 0
     94    redSize   = redSize   > 0 ? redSize   : 0;
     95    greenSize = greenSize > 0 ? greenSize : 0;
     96    blueSize  = blueSize  > 0 ? blueSize  : 0;
     97    alphaSize = alphaSize > 0 ? alphaSize : 0;
     98    depthSize = depthSize > 0 ? depthSize : 0;
     99    stencilSize = stencilSize > 0 ? stencilSize : 0;
     100    sampleCount = sampleCount > 0 ? sampleCount : 0;
     101
     102    eglProperties.setValue(EGL_RED_SIZE,   redSize);
     103    eglProperties.setValue(EGL_GREEN_SIZE, greenSize);
     104    eglProperties.setValue(EGL_BLUE_SIZE,  blueSize);
     105    eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize);
     106    eglProperties.setValue(EGL_DEPTH_SIZE, depthSize);
     107    eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize);
     108    eglProperties.setValue(EGL_SAMPLES, sampleCount);
     109    eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0);
    84110}
    85111
    86112// Updates "format" with the parameters of the selected configuration.
    87 void qt_egl_update_format(const QEglContext& context, QGLFormat& format)
    88 {
    89     EGLint value = 0;
    90 
    91     if (context.configAttrib(EGL_RED_SIZE, &value))
    92         format.setRedBufferSize(value);
    93     if (context.configAttrib(EGL_GREEN_SIZE, &value))
    94         format.setGreenBufferSize(value);
    95     if (context.configAttrib(EGL_BLUE_SIZE, &value))
    96         format.setBlueBufferSize(value);
    97     if (context.configAttrib(EGL_ALPHA_SIZE, &value)) {
    98         format.setAlpha(value != 0);
    99         if (format.alpha())
    100             format.setAlphaBufferSize(value);
    101     }
    102 
    103     if (context.configAttrib(EGL_DEPTH_SIZE, &value)) {
    104         format.setDepth(value != 0);
    105         if (format.depth())
    106             format.setDepthBufferSize(value);
    107     }
    108 
    109     if (context.configAttrib(EGL_LEVEL, &value))
    110         format.setPlane(value);
    111 
    112     if (context.configAttrib(EGL_SAMPLE_BUFFERS, &value)) {
    113         format.setSampleBuffers(value != 0);
    114         if (format.sampleBuffers()) {
    115             context.configAttrib(EGL_SAMPLES, &value);
    116             format.setSamples(value);
    117         }
    118     }
    119 
    120     if (context.configAttrib(EGL_STENCIL_SIZE, &value)) {
    121         format.setStencil(value != 0);
    122         if (format.stencil())
    123             format.setStencilBufferSize(value);
    124     }
     113void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config)
     114{
     115    EGLint redSize     = 0;
     116    EGLint greenSize   = 0;
     117    EGLint blueSize    = 0;
     118    EGLint alphaSize   = 0;
     119    EGLint depthSize   = 0;
     120    EGLint stencilSize = 0;
     121    EGLint sampleCount = 0;
     122    EGLint level       = 0;
     123
     124    EGLDisplay display = QEgl::display();
     125    eglGetConfigAttrib(display, config, EGL_RED_SIZE,     &redSize);
     126    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE,   &greenSize);
     127    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,    &blueSize);
     128    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE,   &alphaSize);
     129    eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE,   &depthSize);
     130    eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
     131    eglGetConfigAttrib(display, config, EGL_SAMPLES,      &sampleCount);
     132    eglGetConfigAttrib(display, config, EGL_LEVEL,        &level);
     133
     134    format.setRedBufferSize(redSize);
     135    format.setGreenBufferSize(greenSize);
     136    format.setBlueBufferSize(blueSize);
     137    format.setAlphaBufferSize(alphaSize);
     138    format.setDepthBufferSize(depthSize);
     139    format.setStencilBufferSize(stencilSize);
     140    format.setSamples(sampleCount);
     141    format.setPlane(level);
     142    format.setDirectRendering(true); // All EGL contexts are direct-rendered
     143    format.setRgba(true);            // EGL doesn't support colour index rendering
     144    format.setStereo(false);         // EGL doesn't support stereo buffers
     145    format.setAccumBufferSize(0);    // EGL doesn't support accululation buffers
     146    format.setDoubleBuffer(true);    // We don't support single buffered EGL contexts
    125147
    126148    // Clear the EGL error state because some of the above may
    127149    // have errored out because the attribute is not applicable
    128150    // to the surface type.  Such errors don't matter.
    129     context.clearError();
     151    eglGetError();
    130152}
    131153
     
    142164    d->cleanup();
    143165    doneCurrent();
    144     if (d->eglContext) {
     166    if (d->eglContext && d->ownsEglContext) {
    145167        d->destroyEglSurfaceForDevice();
    146168        delete d->eglContext;
    147169    }
     170    d->ownsEglContext = false;
    148171    d->eglContext = 0;
    149172    d->eglSurface = EGL_NO_SURFACE;
     
    159182{
    160183    Q_D(QGLContext);
    161     if (!d->valid || !d->eglContext || d->eglSurface == EGL_NO_SURFACE) {
     184    if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) {
    162185        qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
    163186        return;
    164187    }
    165188
    166     if (d->eglContext->makeCurrent(d->eglSurface))
     189    if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) {
    167190        QGLContextPrivate::setCurrentContext(this);
     191        if (!d->workaroundsCached) {
     192            d->workaroundsCached = true;
     193            const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
     194            if (renderer && (strstr(renderer, "SGX") || strstr(renderer, "MBX"))) {
     195                // PowerVR MBX/SGX chips needs to clear all buffers when starting to render
     196                // a new frame, otherwise there will be a performance penalty to pay for
     197                // each frame.
     198                d->workaround_needsFullClearOnEveryFrame = true;
     199
     200                // Older PowerVR SGX drivers (like the one in the N900) have a
     201                // bug which prevents glCopyTexSubImage2D() to work with a POT
     202                // or GL_ALPHA texture bound to an FBO. The only way to
     203                // identify that driver is to check the EGL version number for it.
     204                const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION);
     205                if (egl_version && strstr(egl_version, "1.3"))
     206                    d->workaround_brokenFBOReadBack = true;
     207                else if (egl_version && strstr(egl_version, "1.4"))
     208                    d->workaround_brokenTexSubImage = true;
     209            }
     210        }
     211    }
    168212}
    169213
     
    184228        return;
    185229
    186     d->eglContext->swapBuffers(d->eglSurface);
     230    d->eglContext->swapBuffers(d->eglSurfaceForDevice());
    187231}
    188232
     
    190234{
    191235    if (eglSurface != EGL_NO_SURFACE) {
     236#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN)
     237        // Make sure we don't call eglDestroySurface on a surface which
     238        // was created for a different winId. This applies only to QGLWidget
     239        // paint device, so make sure this is the one we're operating on
     240        // (as opposed to a QGLWindowSurface use case).
     241        if (paintDevice && paintDevice->devType() == QInternal::Widget) {
     242            QWidget *w = static_cast<QWidget *>(paintDevice);
     243            if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) {
     244                if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) {
     245                    qWarning("WARNING: Potential EGL surface leak! Not destroying surface.");
     246                    eglSurface = EGL_NO_SURFACE;
     247                    return;
     248                }
     249            }
     250        }
     251#endif
     252        eglDestroySurface(eglContext->display(), eglSurface);
     253        eglSurface = EGL_NO_SURFACE;
     254    }
     255}
     256
     257EGLSurface QGLContextPrivate::eglSurfaceForDevice() const
     258{
     259    // If a QPixmapData had to create the QGLContext, we don't have a paintDevice
     260    if (!paintDevice)
     261        return eglSurface;
     262
    192263#ifdef Q_WS_X11
    193         // Make sure we don't call eglDestroySurface on a surface which
    194         // was created for a different winId:
    195         if (paintDevice->devType() == QInternal::Widget) {
    196             QGLWidget* w = static_cast<QGLWidget*>(paintDevice);
    197 
    198             if (w->d_func()->eglSurfaceWindowId == w->winId())
    199                 eglDestroySurface(eglContext->display(), eglSurface);
    200             else
    201                 qWarning("WARNING: Potential EGL surface leak!");
    202         } else
     264    if (paintDevice->devType() == QInternal::Pixmap) {
     265        QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data();
     266        if (pmd->classId() == QPixmapData::X11Class) {
     267            QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd);
     268            return (EGLSurface)x11PixmapData->gl_surface;
     269        }
     270    }
    203271#endif
    204             eglDestroySurface(eglContext->display(), eglSurface);
    205         eglSurface = EGL_NO_SURFACE;
    206     }
     272
     273    if (paintDevice->devType() == QInternal::Pbuffer) {
     274        QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice);
     275        return pbuf->d_func()->pbuf;
     276    }
     277
     278    return eglSurface;
     279}
     280
     281void QGLContextPrivate::swapRegion(const QRegion &region)
     282{
     283    if (!valid || !eglContext)
     284        return;
     285
     286    eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), &region);
    207287}
    208288
  • trunk/src/opengl/qgl_egl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555
    5656#include <QtGui/private/qegl_p.h>
     57#include <QtGui/private/qeglcontext_p.h>
     58#include <QtGui/private/qeglproperties_p.h>
    5759
    5860QT_BEGIN_NAMESPACE
     
    6062class QGLFormat;
    6163
    62 void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f);
    63 void qt_egl_update_format(const QEglContext& context, QGLFormat& format);
    64 void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device);
     64void qt_eglproperties_set_glformat(QEglProperties& props, const QGLFormat& format);
     65void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config);
    6566
    6667QT_END_NAMESPACE
  • trunk/src/opengl/qgl_mac.mm

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    698698        NSView *view = qt_mac_nativeview_for(w);
    699699
    700         // ideally we would use QWidget::isVisible(), but we get "invalid drawable" errors
    701         if (![(NSWindow *)qt_mac_window_for(w) isVisible])
    702             return;
     700        // Trying to attach the GL context to the NSView will fail with
     701        // "invalid drawable" if done too soon, but we have to make sure
     702        // the connection is made before the first paint event. Using
     703        // the NSView do to this check fails as the NSView is visible
     704        // before it's safe to connect, and using the NSWindow fails as
     705        // the NSWindow will become visible after the first paint event.
     706        // This leaves us with the QWidget, who's visible state seems
     707        // to match the point in time when it's safe to connect.
     708        if (!w || !w->isVisible())
     709            return; // Not safe to attach GL context to view yet
     710
    703711        if ([static_cast<NSOpenGLContext *>(d->cx) view] != view && ![view isHidden])
    704712            [static_cast<NSOpenGLContext *>(d->cx) setView:view];
     
    805813{
    806814    CFBundleRef bundle = 0;
     815    CFStringRef urlString = QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework"));
    807816    QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
    808                  QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework")), kCFURLPOSIXPathStyle, false);
     817                 urlString, kCFURLPOSIXPathStyle, false);
    809818    if (url)
    810819        bundle = CFBundleCreate(kCFAllocatorDefault, url);
     820    CFRelease(urlString);
    811821    return bundle;
    812822}
     
    814824void *QGLContext::getProcAddress(const QString &proc) const
    815825{
    816     return CFBundleGetFunctionPointerForName(QCFType<CFBundleRef>(qt_getOpenGLBundle()),
    817                                              QCFString(proc));
     826    CFStringRef procName = QCFString(proc).toCFStringRef(proc);
     827    void *result = CFBundleGetFunctionPointerForName(QCFType<CFBundleRef>(qt_getOpenGLBundle()),
     828                                             procName);
     829    CFRelease(procName);
     830    return result;
    818831}
    819832#ifndef QT_MAC_USE_COCOA
  • trunk/src/opengl/qgl_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565#include "qglpaintdevice_p.h"
    6666
    67 #ifndef QT_OPENGL_ES_1_CL
    68 #define q_vertexType float
    69 #define q_vertexTypeEnum GL_FLOAT
    70 #define f2vt(f)     (f)
    71 #define vt2f(x)     (x)
    72 #define i2vt(i)     (float(i))
    73 #else
    74 #define FLOAT2X(f)      (int( (f) * (65536)))
    75 #define X2FLOAT(x)      (float(x) / 65536.0f)
    76 #define f2vt(f)     FLOAT2X(f)
    77 #define i2vt(i)     ((i)*65536)
    78 #define vt2f(x)     X2FLOAT(x)
    79 #define q_vertexType GLfixed
    80 #define q_vertexTypeEnum GL_FIXED
    81 #endif //QT_OPENGL_ES_1_CL
    82 
    83 #if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
    84 QT_BEGIN_INCLUDE_NAMESPACE
    85 
    86 #if defined(QT_OPENGL_ES_2)
    87 #   include <GLES2/gl2.h>
    88 #endif
    89 
    90 #if defined(QT_GLES_EGL)
    91 #   include <GLES/egl.h>
    92 #else
    93 #   include <EGL/egl.h>
    94 #endif
    95 
    96 QT_END_INCLUDE_NAMESPACE
     67#ifndef QT_NO_EGL
     68#include <QtGui/private/qegl_p.h>
    9769#endif
    9870
     
    11587# ifdef old_qDebug
    11688#   undef qDebug
    117 #   define qDebug QT_QDEBUG_MACRO
     89#   define qDebug QT_NO_QDEBUG_MACRO
    11890#   undef old_qDebug
    11991# endif
     
    12597#endif
    12698
    127 #if defined(QT_OPENGL_ES)
     99#ifndef QT_NO_EGL
    128100class QEglContext;
    129101#endif
     
    139111        : ref(1)
    140112    {
    141         opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer;
     113        opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering
     114             | QGL::StencilBuffer | QGL::DeprecatedFunctions;
    142115        pln = 0;
    143116        depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
    144117        numSamples = -1;
    145118        swapInterval = -1;
     119        majorVersion = 1;
     120        minorVersion = 0;
     121        profile = QGLFormat::NoProfile;
    146122    }
    147123    QGLFormatPrivate(const QGLFormatPrivate *other)
     
    157133          alphaSize(other->alphaSize),
    158134          numSamples(other->numSamples),
    159           swapInterval(other->swapInterval)
     135          swapInterval(other->swapInterval),
     136          majorVersion(other->majorVersion),
     137          minorVersion(other->minorVersion),
     138          profile(other->profile)
    160139    {
    161140    }
     
    172151    int numSamples;
    173152    int swapInterval;
     153    int majorVersion;
     154    int minorVersion;
     155    QGLFormat::OpenGLContextProfile profile;
    174156};
    175157
     
    183165                       , wsurf(0)
    184166#endif
    185 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     167#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
     168                       , eglSurfaceWindowId(0)
     169#endif
     170#if defined(Q_OS_SYMBIAN)
    186171                       , eglSurfaceWindowId(0)
    187172#endif
     
    196181    bool renderCxPm(QPixmap *pixmap);
    197182    void cleanupColormaps();
     183    void aboutToDestroy() {
     184        if (glcx)
     185            glcx->reset();
     186    }
    198187
    199188    QGLContext *glcx;
     
    213202#elif defined(Q_WS_X11)
    214203    QGLOverlayWidget *olw;
    215 #if defined(QT_OPENGL_ES)
    216     void recreateEglSurface(bool force);
     204#ifndef QT_NO_EGL
     205    void recreateEglSurface();
    217206    WId eglSurfaceWindowId;
    218207#endif
     
    223212    QWSGLWindowSurface *wsurf;
    224213#endif
     214#ifdef Q_OS_SYMBIAN
     215    void recreateEglSurface();
     216    WId eglSurfaceWindowId;
     217#endif
    225218};
    226219
     
    249242    static void removeShare(const QGLContext *context);
    250243private:
    251     QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
     244    QGLContextGroup(const QGLContext *context);
    252245
    253246    QGLExtensionFuncs m_extensionFuncs;
     
    292285        ETC1TextureCompression  = 0x00010000,
    293286        PVRTCTextureCompression = 0x00020000,
    294         FragmentShader          = 0x00040000
     287        FragmentShader          = 0x00040000,
     288        ElementIndexUint        = 0x00080000,
     289        Depth24                 = 0x00100000
    295290    };
    296291    Q_DECLARE_FLAGS(Extensions, Extension)
    297292
    298293    static Extensions glExtensions();
    299 
    300 private:
    301294    static Extensions currentContextExtensions();
    302295};
     
    325318
    326319class QGLTexture;
     320class QGLTextureDestroyer;
    327321
    328322// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
     
    334328    Q_DECLARE_PUBLIC(QGLContext)
    335329public:
    336     explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
     330    explicit QGLContextPrivate(QGLContext *context);
    337331    ~QGLContextPrivate();
    338332    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
     
    351345    void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
    352346    void syncGlState(); // Makes sure the GL context's state is what we think it is
     347    void swapRegion(const QRegion &region);
     348
     349#if defined(Q_WS_WIN)
     350    void updateFormatVersion();
     351#endif
    353352
    354353#if defined(Q_WS_WIN)
     
    361360    HDC hbitmap_hdc;
    362361#endif
    363 #if defined(QT_OPENGL_ES)
     362#ifndef QT_NO_EGL
     363    uint ownsEglContext : 1;
    364364    QEglContext *eglContext;
    365365    EGLSurface eglSurface;
    366366    void destroyEglSurfaceForDevice();
     367    EGLSurface eglSurfaceForDevice() const;
    367368#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
    368369    void* cx;
     
    376377    int screen;
    377378    QHash<QPixmapData*, QPixmap> boundPixmaps;
    378     QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
     379    QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key,
    379380                                            QGLContext::BindOptions options);
    380381    static void destroyGlSurfaceForPixmap(QPixmapData*);
     
    397398    uint version_flags_cached : 1;
    398399    uint extension_flags_cached : 1;
     400
     401    // workarounds for driver/hw bugs on different platforms
     402    uint workaround_needsFullClearOnEveryFrame : 1;
     403    uint workaround_brokenFBOReadBack : 1;
     404    uint workaround_brokenTexSubImage : 1;
     405    uint workaroundsCached : 1;
     406
     407    uint workaround_brokenTextureFromPixmap : 1;
     408    uint workaround_brokenTextureFromPixmap_init : 1;
     409
    399410    QPaintDevice *paintDevice;
    400411    QColor transpColor;
     
    409420    GLuint default_fbo;
    410421    QPaintEngine *active_engine;
     422    QGLTextureDestroyer *texture_destroyer;
    411423
    412424    bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
     
    418430#endif
    419431
    420 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
     432#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
    421433    static QGLExtensionFuncs qt_extensionFuncs;
    422     static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
     434    static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *);
    423435#endif
    424436
    425437    static void setCurrentContext(QGLContext *context);
    426 };
    427 
    428 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff
    429 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
    430 {
    431     Q_OBJECT
    432 public:
    433     QGLSignalProxy() : QObject() {}
    434     void emitAboutToDestroyContext(const QGLContext *context) {
    435         emit aboutToDestroyContext(context);
    436     }
    437     static QGLSignalProxy *instance();
    438 Q_SIGNALS:
    439     void aboutToDestroyContext(const QGLContext *context);
    440438};
    441439
     
    482480};
    483481
     482class QGLTextureDestroyer : public QObject
     483{
     484    Q_OBJECT
     485public:
     486    QGLTextureDestroyer() : QObject() {
     487        qRegisterMetaType<GLuint>("GLuint");
     488        connect(this, SIGNAL(freeTexture(QGLContext *, QPixmapData *, GLuint)),
     489                this, SLOT(freeTexture_slot(QGLContext *, QPixmapData *, GLuint)));
     490    }
     491    void emitFreeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id) {
     492        emit freeTexture(context, boundPixmap, id);
     493    }
     494
     495Q_SIGNALS:
     496    void freeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id);
     497
     498private slots:
     499    void freeTexture_slot(QGLContext *context, QPixmapData *boundPixmap, GLuint id) {
     500#if defined(Q_WS_X11)
     501        if (boundPixmap) {
     502            QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
     503            context->makeCurrent();
     504            // Although glXReleaseTexImage is a glX call, it must be called while there
     505            // is a current context - the context the pixmap was bound to a texture in.
     506            // Otherwise the release doesn't do anything and you get BadDrawable errors
     507            // when you come to delete the context.
     508            QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
     509            glDeleteTextures(1, &id);
     510            if (oldContext)
     511                oldContext->makeCurrent();
     512            return;
     513        }
     514#endif
     515        QGLShareContextScope scope(context);
     516        glDeleteTextures(1, &id);
     517    }
     518};
     519
     520// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
     521class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
     522{
     523    Q_OBJECT
     524public:
     525    void emitAboutToDestroyContext(const QGLContext *context) {
     526        emit aboutToDestroyContext(context);
     527    }
     528    static QGLSignalProxy *instance();
     529Q_SIGNALS:
     530    void aboutToDestroyContext(const QGLContext *context);
     531};
     532
    484533class QGLTexture {
    485534public:
     
    498547        if (options & QGLContext::MemoryManagedBindOption) {
    499548            Q_ASSERT(context);
    500             QGLShareContextScope scope(context);
    501 #if defined(Q_WS_X11)
    502             // Although glXReleaseTexImage is a glX call, it must be called while there
    503             // is a current context - the context the pixmap was bound to a texture in.
    504             // Otherwise the release doesn't do anything and you get BadDrawable errors
    505             // when you come to delete the context.
    506             if (boundPixmap)
    507                 QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
    508 #endif
    509             glDeleteTextures(1, &id);
     549#if !defined(Q_WS_X11)
     550            QPixmapData *boundPixmap = 0;
     551#endif
     552            context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id);
    510553        }
    511554     }
     
    531574};
    532575
     576struct QGLTextureCacheKey {
     577    qint64 key;
     578    QGLContextGroup *group;
     579};
     580
     581inline bool operator==(const QGLTextureCacheKey &a, const QGLTextureCacheKey &b)
     582{
     583    return a.key == b.key && a.group == b.group;
     584}
     585
     586inline uint qHash(const QGLTextureCacheKey &key)
     587{
     588    return qHash(key.key) ^ qHash(key.group);
     589}
     590
     591
    533592class Q_AUTOTEST_EXPORT QGLTextureCache {
    534593public:
     
    537596
    538597    void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
    539     void remove(quint64 key) { m_cache.remove(key); }
     598    void remove(qint64 key);
     599    inline int size();
     600    inline void setMaxCost(int newMax);
     601    inline int maxCost();
     602    inline QGLTexture* getTexture(QGLContext *ctx, qint64 key);
     603
    540604    bool remove(QGLContext *ctx, GLuint textureId);
    541605    void removeContextTextures(QGLContext *ctx);
    542     int size() { return m_cache.size(); }
    543     void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); }
    544     int maxCost() {return m_cache.maxCost(); }
    545     QGLTexture* getTexture(quint64 key) { return m_cache.object(key); }
    546 
    547606    static QGLTextureCache *instance();
    548     static void deleteIfEmpty();
    549607    static void cleanupTexturesForCacheKey(qint64 cacheKey);
    550608    static void cleanupTexturesForPixampData(QPixmapData* pixmap);
     
    552610
    553611private:
    554     QCache<qint64, QGLTexture> m_cache;
    555 };
    556 
     612    QCache<QGLTextureCacheKey, QGLTexture> m_cache;
     613    QReadWriteLock m_lock;
     614};
     615
     616int QGLTextureCache::size() {
     617    QReadLocker locker(&m_lock);
     618    return m_cache.size();
     619}
     620
     621void QGLTextureCache::setMaxCost(int newMax)
     622{
     623    QWriteLocker locker(&m_lock);
     624    m_cache.setMaxCost(newMax);
     625}
     626
     627int QGLTextureCache::maxCost()
     628{
     629    QReadLocker locker(&m_lock);
     630    return m_cache.maxCost();
     631}
     632
     633QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key)
     634{
     635    QReadLocker locker(&m_lock);
     636    const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
     637    return m_cache.object(cacheKey);
     638}
    557639
    558640extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine();
  • trunk/src/opengl/qgl_qws.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    118118    else
    119119        return false;
    120 }
    121 
    122 void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
    123 {
    124     // Find the QGLScreen for this paint device.
    125     QGLScreen *glScreen = glScreenForDevice(device);
    126     if (!glScreen) {
    127         qWarning("QGLContext::chooseContext(): The screen is not a QGLScreen");
    128         return;
    129     }
    130     int devType = device->devType();
    131     if (devType == QInternal::Image)
    132         props.setPixelFormat(static_cast<QImage *>(device)->format());
    133     else
    134         props.setPixelFormat(glScreen->pixelFormat());
    135120}
    136121
     
    198183    // Get the display and initialize it.
    199184    d->eglContext = new QEglContext();
     185    d->ownsEglContext = true;
    200186    d->eglContext->setApi(QEgl::OpenGL);
    201187
    202188    // Construct the configuration we need for this surface.
    203189    QEglProperties configProps;
    204     qt_egl_add_platform_config(configProps, device());
    205     qt_egl_set_format(configProps, devType, d->glFormat);
     190    qt_eglproperties_set_glformat(configProps, d->glFormat);
     191    configProps.setDeviceType(devType);
     192    configProps.setPaintDeviceFormat(device());
    206193    configProps.setRenderableType(QEgl::OpenGL);
    207194
     
    215202
    216203    // Inform the higher layers about the actual format properties.
    217     qt_egl_update_format(*(d->eglContext), d->glFormat);
     204    qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
    218205
    219206    // Create a new context for the configuration.
  • trunk/src/opengl/qgl_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    123123#endif
    124124
     125#ifndef WGL_ARB_create_context
     126#define WGL_CONTEXT_MAJOR_VERSION_ARB               0x2091
     127#define WGL_CONTEXT_MINOR_VERSION_ARB               0x2092
     128#define WGL_CONTEXT_LAYER_PLANE_ARB                 0x2093
     129#define WGL_CONTEXT_FLAGS_ARB                       0x2094
     130#define WGL_CONTEXT_PROFILE_MASK_ARB                0x9126
     131#define WGL_CONTEXT_DEBUG_BIT_ARB                   0x0001
     132#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB      0x0002
     133#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB            0x0001
     134#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB   0x0002
     135// Error codes returned by GetLastError().
     136#define ERROR_INVALID_VERSION_ARB                   0x2095
     137#define ERROR_INVALID_PROFILE_ARB                   0x2096
     138#endif
     139
     140#ifndef GL_VERSION_3_2
     141#define GL_CONTEXT_PROFILE_MASK                     0x9126
     142#define GL_MAJOR_VERSION                            0x821B
     143#define GL_MINOR_VERSION                            0x821C
     144#define GL_NUM_EXTENSIONS                           0x821D
     145#define GL_CONTEXT_FLAGS                            0x821E
     146#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT      0x0001
     147#endif
     148
    125149QT_BEGIN_NAMESPACE
    126150
     
    683707}
    684708
     709static bool qgl_create_context(HDC hdc, QGLContextPrivate *d, QGLContextPrivate *shareContext)
     710{
     711    d->rc = 0;
     712
     713    typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARB)(HDC, HGLRC, const int *);
     714    PFNWGLCREATECONTEXTATTRIBSARB wglCreateContextAttribsARB =
     715        (PFNWGLCREATECONTEXTATTRIBSARB) wglGetProcAddress("wglCreateContextAttribsARB");
     716    if (wglCreateContextAttribsARB) {
     717        int attributes[11];
     718        int attribIndex = 0;
     719        const int major = d->reqFormat.majorVersion();
     720        const int minor = d->reqFormat.minorVersion();
     721        attributes[attribIndex++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
     722        attributes[attribIndex++] = major;
     723        attributes[attribIndex++] = WGL_CONTEXT_MINOR_VERSION_ARB;
     724        attributes[attribIndex++] = minor;
     725
     726        if (major >= 3 && !d->reqFormat.testOption(QGL::DeprecatedFunctions)) {
     727            attributes[attribIndex++] = WGL_CONTEXT_FLAGS_ARB;
     728            attributes[attribIndex++] = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
     729        }
     730
     731        if ((major == 3 && minor >= 2) || major > 3) {
     732            switch (d->reqFormat.profile()) {
     733            case QGLFormat::NoProfile:
     734                break;
     735            case QGLFormat::CoreProfile:
     736                attributes[attribIndex++] = WGL_CONTEXT_PROFILE_MASK_ARB;
     737                attributes[attribIndex++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
     738                break;
     739            case QGLFormat::CompatibilityProfile:
     740                attributes[attribIndex++] = WGL_CONTEXT_PROFILE_MASK_ARB;
     741                attributes[attribIndex++] = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
     742                break;
     743            default:
     744                qWarning("QGLContext::chooseContext(): Context profile not supported.");
     745                return false;
     746            }
     747        }
     748
     749        if (d->reqFormat.plane() != 0) {
     750            attributes[attribIndex++] = WGL_CONTEXT_LAYER_PLANE_ARB;
     751            attributes[attribIndex++] = d->reqFormat.plane();
     752        }
     753
     754        attributes[attribIndex++] = 0; // Terminate list.
     755        d->rc = wglCreateContextAttribsARB(hdc, shareContext && shareContext->valid
     756                                           ? shareContext->rc : 0, attributes);
     757        if (d->rc) {
     758            if (shareContext)
     759                shareContext->sharing = d->sharing = true;
     760            return true;
     761        }
     762    }
     763
     764    d->rc = wglCreateLayerContext(hdc, d->reqFormat.plane());
     765    if (d->rc && shareContext && shareContext->valid)
     766        shareContext->sharing = d->sharing = wglShareLists(shareContext->rc, d->rc);
     767    return d->rc != 0;
     768}
     769
     770void QGLContextPrivate::updateFormatVersion()
     771{
     772    const GLubyte *s = glGetString(GL_VERSION);
     773
     774    if (!(s && s[0] >= '0' && s[0] <= '9' && s[1] == '.' && s[2] >= '0' && s[2] <= '9')) {
     775        if (!s)
     776            qWarning("QGLContext::chooseContext(): OpenGL version string is null.");
     777        else
     778            qWarning("QGLContext::chooseContext(): Unexpected OpenGL version string format.");
     779        glFormat.setVersion(0, 0);
     780        glFormat.setProfile(QGLFormat::NoProfile);
     781        glFormat.setOption(QGL::DeprecatedFunctions);
     782        return;
     783    }
     784
     785    int major = s[0] - '0';
     786    int minor = s[2] - '0';
     787    glFormat.setVersion(major, minor);
     788
     789    if (major < 3) {
     790        glFormat.setProfile(QGLFormat::NoProfile);
     791        glFormat.setOption(QGL::DeprecatedFunctions);
     792    } else {
     793        GLint value = 0;
     794        if (major > 3 || minor >= 2)
     795            glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
     796
     797        switch (value) {
     798        case WGL_CONTEXT_CORE_PROFILE_BIT_ARB:
     799            glFormat.setProfile(QGLFormat::CoreProfile);
     800            break;
     801        case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
     802            glFormat.setProfile(QGLFormat::CompatibilityProfile);
     803            break;
     804        default:
     805            glFormat.setProfile(QGLFormat::NoProfile);
     806            break;
     807        }
     808
     809        glGetIntegerv(GL_CONTEXT_FLAGS, &value);
     810        if (value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
     811            glFormat.setOption(QGL::NoDeprecatedFunctions);
     812        else
     813            glFormat.setOption(QGL::DeprecatedFunctions);
     814    }
     815}
     816
    685817bool QGLContext::chooseContext(const QGLContext* shareContext)
    686818{
     819    QGLContextPrivate *share = shareContext ? const_cast<QGLContext *>(shareContext)->d_func() : 0;
     820
    687821    Q_D(QGLContext);
    688822    // workaround for matrox driver:
     
    742876        }
    743877
    744         d->rc = wglCreateLayerContext(myDc, d->glFormat.plane());
    745         if (!d->rc) {
     878        if (!qgl_create_context(myDc, d, share)) {
    746879            qwglError("QGLContext::chooseContext()", "CreateLayerContext");
    747880            result = false;
     
    793926            d->cmap->setEntry(lpfd.crTransparent, qRgb(1, 2, 3));//, QGLCmap::Reserved);
    794927        }
    795 
    796         if (shareContext && shareContext->isValid()) {
    797             QGLContext *share = const_cast<QGLContext *>(shareContext);
    798             d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
    799             share->d_func()->sharing = d->sharing;
    800         }
    801 
    802         goto end;
    803     }
    804     {
     928    } else {
    805929        PIXELFORMATDESCRIPTOR pfd;
    806930        PIXELFORMATDESCRIPTOR realPfd;
     
    841965        }
    842966
    843         if (!(d->rc = wglCreateLayerContext(myDc, 0))) {
     967        if (!qgl_create_context(myDc, d, share)) {
    844968            qwglError("QGLContext::chooseContext()", "wglCreateContext");
    845969            result = false;
    846970            goto end;
    847         }
    848 
    849         if (shareContext && shareContext->isValid()) {
    850             d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
    851             const_cast<QGLContext *>(shareContext)->d_func()->sharing = d->sharing;
    852971        }
    853972
     
    866985    // vblanking
    867986    wglMakeCurrent(myDc, d->rc);
     987    if (d->rc)
     988        d->updateFormatVersion();
     989
    868990    typedef BOOL (APIENTRYP PFNWGLSWAPINTERVALEXT) (int interval);
    869991    typedef int (APIENTRYP PFNWGLGETSWAPINTERVALEXT) (void);
     
    9211043        iAttributes[i++] = TRUE;
    9221044        iAttributes[i++] = WGL_COLOR_BITS_ARB;
    923         iAttributes[i++] = 32;
     1045        iAttributes[i++] = 24;
    9241046        iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
    9251047        iAttributes[i++] = d->glFormat.doubleBuffer();
     
    11591281{
    11601282    Q_D(QGLContext);
    1161     if (d->rc == wglGetCurrentContext() || !d->valid)        // already current
     1283    if (d->rc == wglGetCurrentContext() || !d->valid)       // already current
    11621284        return;
     1285
    11631286    if (d->win) {
    11641287        d->dc = GetDC(d->win);
  • trunk/src/opengl/qgl_wince.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555#include <windows.h>
    5656
    57 #include <private/qegl_p.h>
     57#include <private/qeglproperties_p.h>
     58#include <private/qeglcontext_p.h>
    5859#include <private/qgl_egl_p.h>
    59 #include <private/qgl_cl_p.h>
    6060
    6161
     
    121121  QGLFormat Win32/WGL-specific code
    122122 *****************************************************************************/
    123 
    124 void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
    125 {
    126     int devType = device->devType();
    127     if (devType == QInternal::Image)
    128         props.setPixelFormat(static_cast<QImage *>(device)->format());
    129     else
    130         props.setPixelFormat(QImage::Format_RGB16);
    131 }
    132 
    133123
    134124static bool opengl32dll = false;
     
    155145    // Get the display and initialize it.
    156146    d->eglContext = new QEglContext();
     147    d->ownsEglContext = true;
    157148    d->eglContext->setApi(QEgl::OpenGL);
    158149
    159150    // Construct the configuration we need for this surface.
    160151    QEglProperties configProps;
    161     qt_egl_add_platform_config(configProps, device());
    162     qt_egl_set_format(configProps, devType, d->glFormat);
     152    qt_eglproperties_set_glformat(configProps, d->glFormat);
     153    configProps.setDeviceType(devType);
     154    configProps.setPaintDeviceFormat(device());
    163155    configProps.setRenderableType(QEgl::OpenGL);
    164156
     
    172164
    173165    // Inform the higher layers about the actual format properties.
    174     qt_egl_update_format(*(d->eglContext), d->glFormat);
     166    qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
    175167
    176168    // Create a new context for the configuration.
  • trunk/src/opengl/qgl_x11.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555#include <private/qpixmap_x11_p.h>
    5656#include <private/qimagepixmapcleanuphooks_p.h>
     57#include <private/qunicodetables_p.h>
    5758#ifdef Q_OS_HPUX
    5859// for GLXPBuffer
     
    114115#define GLX_TEXTURE_RECTANGLE_EXT          0x20DD
    115116#define GLX_FRONT_LEFT_EXT                 0x20DE
     117#endif
     118
     119#ifndef GLX_ARB_create_context
     120#define GLX_CONTEXT_DEBUG_BIT_ARB          0x00000001
     121#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
     122#define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091
     123#define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092
     124#define GLX_CONTEXT_FLAGS_ARB              0x2094
     125#endif
     126
     127#ifndef GLX_ARB_create_context_profile
     128#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB   0x00000001
     129#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
     130#define GLX_CONTEXT_PROFILE_MASK_ARB       0x9126
    116131#endif
    117132
     
    400415        find_trans_colors();
    401416    return trans_colors.size() > 0;
     417}
     418
     419static bool buildSpec(int* spec, const QGLFormat& f, QPaintDevice* paintDevice,
     420                      int bufDepth, bool onlyFBConfig = false)
     421{
     422    int i = 0;
     423    spec[i++] = GLX_LEVEL;
     424    spec[i++] = f.plane();
     425    const QX11Info *xinfo = qt_x11Info(paintDevice);
     426    bool useFBConfig = onlyFBConfig;
     427
     428#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX)
     429    /*
     430      HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
     431      Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
     432     */
     433    QWidget* widget = 0;
     434    if (paintDevice->devType() == QInternal::Widget)
     435        widget = static_cast<QWidget*>(paintDevice);
     436
     437    // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
     438    if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
     439        useFBConfig = true;
     440#endif
     441
     442#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
     443    static bool useTranspExt = false;
     444    static bool useTranspExtChecked = false;
     445    if (f.plane() && !useTranspExtChecked && paintDevice) {
     446        QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
     447        useTranspExt = extensions.match("GLX_EXT_visual_info");
     448        //# (A bit simplistic; that could theoretically be a substring)
     449        if (useTranspExt) {
     450            QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
     451            useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround
     452            if (useTranspExt) {
     453                // bug workaround - some systems (eg. FireGL) refuses to return an overlay
     454                // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if
     455                // the implementation supports transparent overlays
     456                int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
     457                                  f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
     458                                  XNone };
     459                XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec);
     460                if (!vinf) {
     461                    useTranspExt = false;
     462                }
     463            }
     464        }
     465
     466        useTranspExtChecked = true;
     467    }
     468    if (f.plane() && useTranspExt && !useFBConfig) {
     469        // Required to avoid non-transparent overlay visual(!) on some systems
     470        spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
     471        spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
     472    }
     473#endif
     474
     475#if defined(GLX_VERSION_1_3)  && !defined(Q_OS_HPUX)
     476    // GLX_RENDER_TYPE is only in glx >=1.3
     477    if (useFBConfig) {
     478        spec[i++] = GLX_RENDER_TYPE;
     479        spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
     480    }
     481#endif
     482
     483    if (f.doubleBuffer())
     484        spec[i++] = GLX_DOUBLEBUFFER;
     485        if (useFBConfig)
     486            spec[i++] = True;
     487    if (f.depth()) {
     488        spec[i++] = GLX_DEPTH_SIZE;
     489        spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
     490    }
     491    if (f.stereo()) {
     492        spec[i++] = GLX_STEREO;
     493        if (useFBConfig)
     494            spec[i++] = True;
     495    }
     496    if (f.stencil()) {
     497        spec[i++] = GLX_STENCIL_SIZE;
     498        spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
     499    }
     500    if (f.rgba()) {
     501        if (!useFBConfig)
     502            spec[i++] = GLX_RGBA;
     503        spec[i++] = GLX_RED_SIZE;
     504        spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
     505        spec[i++] = GLX_GREEN_SIZE;
     506        spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
     507        spec[i++] = GLX_BLUE_SIZE;
     508        spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
     509        if (f.alpha()) {
     510            spec[i++] = GLX_ALPHA_SIZE;
     511            spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
     512        }
     513        if (f.accum()) {
     514            spec[i++] = GLX_ACCUM_RED_SIZE;
     515            spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
     516            spec[i++] = GLX_ACCUM_GREEN_SIZE;
     517            spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
     518            spec[i++] = GLX_ACCUM_BLUE_SIZE;
     519            spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
     520            if (f.alpha()) {
     521                spec[i++] = GLX_ACCUM_ALPHA_SIZE;
     522                spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
     523            }
     524        }
     525    } else {
     526        spec[i++] = GLX_BUFFER_SIZE;
     527        spec[i++] = bufDepth;
     528    }
     529
     530    if (f.sampleBuffers()) {
     531        spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
     532        spec[i++] = 1;
     533        spec[i++] = GLX_SAMPLES_ARB;
     534        spec[i++] = f.samples() == -1 ? 4 : f.samples();
     535    }
     536
     537#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     538    if (useFBConfig) {
     539        spec[i++] = GLX_DRAWABLE_TYPE;
     540        switch(paintDevice->devType()) {
     541        case QInternal::Pixmap:
     542            spec[i++] = GLX_PIXMAP_BIT;
     543            break;
     544        case QInternal::Pbuffer:
     545            spec[i++] = GLX_PBUFFER_BIT;
     546            break;
     547        default:
     548            qWarning("QGLContext: Unknown paint device type %d", paintDevice->devType());
     549            // Fall-through & assume it's a window
     550        case QInternal::Widget:
     551            spec[i++] = GLX_WINDOW_BIT;
     552            break;
     553        };
     554    }
     555#endif
     556
     557    spec[i] = XNone;
     558    return useFBConfig;
    402559}
    403560
     
    494651    }
    495652
     653    const int major = d->reqFormat.majorVersion();
     654    const int minor = d->reqFormat.minorVersion();
     655    const int profile = d->reqFormat.profile() == QGLFormat::CompatibilityProfile
     656        ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
     657        : GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
     658
    496659    d->cx = 0;
    497     if (shareContext) {
     660
     661#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     662    /*
     663      HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
     664      Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
     665     */
     666    if ((major == 3 && minor >= 2) || major > 3) {
     667        QGLTemporaryContext *tmpContext = 0;
     668        if (!QGLContext::currentContext())
     669            tmpContext = new QGLTemporaryContext;
     670
     671        int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major,
     672                             GLX_CONTEXT_MINOR_VERSION_ARB, minor,
     673                             GLX_CONTEXT_PROFILE_MASK_ARB, profile,
     674                             0 };
     675
     676        typedef GLXContext ( * Q_PFNGLXCREATECONTEXTATTRIBSARBPROC)
     677            (Display* dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
     678
     679
     680        Q_PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
     681            (Q_PFNGLXCREATECONTEXTATTRIBSARBPROC) qglx_getProcAddress("glXCreateContextAttribsARB");
     682
     683        if (glXCreateContextAttribs) {
     684            int spec[45];
     685            glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BUFFER_SIZE, &res);
     686            buildSpec(spec, format(), d->paintDevice, res, true);
     687
     688            GLXFBConfig *configs;
     689            int configCount = 0;
     690            configs = glXChooseFBConfig(disp, xinfo->screen(), spec, &configCount);
     691
     692            if (configs && configCount > 0) {
     693                d->cx = glXCreateContextAttribs(disp, configs[0],
     694                    shareContext ? (GLXContext)shareContext->d_func()->cx : 0, direct, attributes);
     695                if (!d->cx && shareContext) {
     696                    shareContext = 0;
     697                    d->cx = glXCreateContextAttribs(disp, configs[0], 0, direct, attributes);
     698                }
     699                d->screen = ((XVisualInfo*)d->vi)->screen;
     700            }
     701            XFree(configs);
     702        } else {
     703            qWarning("QGLContext::chooseContext(): OpenGL %d.%d is not supported", major, minor);
     704        }
     705
     706        if (tmpContext)
     707            delete tmpContext;
     708    }
     709#else
     710    Q_UNUSED(major);
     711    Q_UNUSED(minor);
     712    Q_UNUSED(profile);
     713#endif
     714
     715    if (!d->cx && shareContext) {
    498716        d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi,
    499717                               (GLXContext)shareContext->d_func()->cx, direct);
    500718        d->screen = ((XVisualInfo*)d->vi)->screen;
    501         if (d->cx) {
    502             QGLContext *share = const_cast<QGLContext *>(shareContext);
    503             d->sharing = true;
    504             share->d_func()->sharing = true;
    505         }
    506719    }
    507720    if (!d->cx) {
    508721        d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct);
    509722        d->screen = ((XVisualInfo*)d->vi)->screen;
    510     }
     723        shareContext = 0;
     724    }
     725
     726    if (shareContext && d->cx) {
     727        QGLContext *share = const_cast<QGLContext *>(shareContext);
     728        d->sharing = true;
     729        share->d_func()->sharing = true;
     730    }
     731
    511732    if (!d->cx)
    512733        return false;
     
    607828    Q_D(QGLContext);
    608829    int spec[45];
    609     int i = 0;
    610     spec[i++] = GLX_LEVEL;
    611     spec[i++] = f.plane();
    612830    const QX11Info *xinfo = qt_x11Info(d->paintDevice);
    613     bool useFBConfig = false;
    614 
    615 #if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX)
    616     /*
    617       HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
    618       Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
    619      */
    620     QWidget* widget = 0;
    621     if (d->paintDevice->devType() == QInternal::Widget)
    622         widget = static_cast<QWidget*>(d->paintDevice);
    623 
    624     // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
    625     if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
    626         useFBConfig = true;
    627 #endif
    628 
    629 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
    630     static bool useTranspExt = false;
    631     static bool useTranspExtChecked = false;
    632     if (f.plane() && !useTranspExtChecked && d->paintDevice) {
    633         QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
    634         useTranspExt = extensions.match("GLX_EXT_visual_info");
    635         //# (A bit simplistic; that could theoretically be a substring)
    636         if (useTranspExt) {
    637             QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
    638             useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround
    639             if (useTranspExt) {
    640                 // bug workaround - some systems (eg. FireGL) refuses to return an overlay
    641                 // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if
    642                 // the implementation supports transparent overlays
    643                 int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
    644                                   f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
    645                                   XNone };
    646                 XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec);
    647                 if (!vinf) {
    648                     useTranspExt = false;
    649                 }
    650             }
    651         }
    652 
    653         useTranspExtChecked = true;
    654     }
    655     if (f.plane() && useTranspExt && !useFBConfig) {
    656         // Required to avoid non-transparent overlay visual(!) on some systems
    657         spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
    658         spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
    659     }
    660 #endif
    661 
    662 #if defined(GLX_VERSION_1_3)  && !defined(Q_OS_HPUX)
    663     // GLX_RENDER_TYPE is only in glx >=1.3
    664     if (useFBConfig) {
    665         spec[i++] = GLX_RENDER_TYPE;
    666         spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
    667     }
    668 #endif
    669 
    670     if (f.doubleBuffer())
    671         spec[i++] = GLX_DOUBLEBUFFER;
    672         if (useFBConfig)
    673             spec[i++] = True;
    674     if (f.depth()) {
    675         spec[i++] = GLX_DEPTH_SIZE;
    676         spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
    677     }
    678     if (f.stereo()) {
    679         spec[i++] = GLX_STEREO;
    680         if (useFBConfig)
    681             spec[i++] = True;
    682     }
    683     if (f.stencil()) {
    684         spec[i++] = GLX_STENCIL_SIZE;
    685         spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
    686     }
    687     if (f.rgba()) {
    688         if (!useFBConfig)
    689             spec[i++] = GLX_RGBA;
    690         spec[i++] = GLX_RED_SIZE;
    691         spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
    692         spec[i++] = GLX_GREEN_SIZE;
    693         spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
    694         spec[i++] = GLX_BLUE_SIZE;
    695         spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
    696         if (f.alpha()) {
    697             spec[i++] = GLX_ALPHA_SIZE;
    698             spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
    699         }
    700         if (f.accum()) {
    701             spec[i++] = GLX_ACCUM_RED_SIZE;
    702             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
    703             spec[i++] = GLX_ACCUM_GREEN_SIZE;
    704             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
    705             spec[i++] = GLX_ACCUM_BLUE_SIZE;
    706             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
    707             if (f.alpha()) {
    708                 spec[i++] = GLX_ACCUM_ALPHA_SIZE;
    709                 spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
    710             }
    711         }
    712     } else {
    713         spec[i++] = GLX_BUFFER_SIZE;
    714         spec[i++] = bufDepth;
    715     }
    716 
    717     if (f.sampleBuffers()) {
    718         spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
    719         spec[i++] = 1;
    720         spec[i++] = GLX_SAMPLES_ARB;
    721         spec[i++] = f.samples() == -1 ? 4 : f.samples();
    722     }
    723 
    724 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
    725     if (useFBConfig) {
    726         spec[i++] = GLX_DRAWABLE_TYPE;
    727         switch(d->paintDevice->devType()) {
    728         case QInternal::Pixmap:
    729             spec[i++] = GLX_PIXMAP_BIT;
    730             break;
    731         case QInternal::Pbuffer:
    732             spec[i++] = GLX_PBUFFER_BIT;
    733             break;
    734         default:
    735             qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType());
    736             // Fall-through & assume it's a window
    737         case QInternal::Widget:
    738             spec[i++] = GLX_WINDOW_BIT;
    739             break;
    740         };
    741     }
    742 #endif
    743 
    744     spec[i] = XNone;
    745 
     831    bool useFBConfig = buildSpec(spec, f, d->paintDevice, bufDepth, false);
    746832
    747833    XVisualInfo* chosenVisualInfo = 0;
     
    756842            break; // fallback to trying glXChooseVisual
    757843
    758         for (i = 0; i < configCount; ++i) {
     844        for (int i = 0; i < configCount; ++i) {
    759845            XVisualInfo* vi;
    760846            vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]);
     
    844930        ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx);
    845931    } else if (d->paintDevice->devType() == QInternal::Widget) {
    846         ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx);
     932        ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->internalWinId(), (GLXContext)d->cx);
    847933    }
    848934    if (!ok)
     
    16721758
    16731759
    1674 QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key,
     1760QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key,
    16751761                                                           QGLContext::BindOptions options)
    16761762{
     
    16781764    return 0;
    16791765#else
     1766
     1767    // Check we have GLX 1.3, as it is needed for glXCreatePixmap & glXDestroyPixmap
     1768    int majorVersion = 0;
     1769    int minorVersion = 0;
     1770    glXQueryVersion(X11->display, &majorVersion, &minorVersion);
     1771    if (majorVersion < 1 || (majorVersion == 1 && minorVersion < 3))
     1772        return 0;
     1773
    16801774    Q_Q(QGLContext);
    16811775
    1682     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     1776    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
     1777    Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
     1778
     1779    // We can't use TFP if the pixmap has a separate X11 mask
     1780    if (pixmapData->x11_mask)
     1781        return 0;
    16831782
    16841783    if (!qt_resolveTextureFromPixmap(paintDevice))
    16851784        return 0;
    16861785
    1687     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
    16881786    const QX11Info &x11Info = pixmapData->xinfo;
    16891787
     
    17541852            return 0;
    17551853
    1756         pixmapData->gl_surface = (Qt::HANDLE)glxPixmap;
     1854        pixmapData->gl_surface = (void*)glxPixmap;
    17571855
    17581856        // Make sure the cleanup hook gets called so we can delete the glx pixmap
     
    17661864
    17671865    glBindTexture(GL_TEXTURE_2D, textureId);
     1866    GLuint filtering = (options & QGLContext::LinearFilteringBindOption) ? GL_LINEAR : GL_NEAREST;
     1867    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
     1868    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
    17681869
    17691870    if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted)))
  • trunk/src/opengl/qgl_x11egl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include <private/qt_x11_p.h>
    4444#include <private/qpixmap_x11_p.h>
    45 #include <private/qimagepixmapcleanuphooks_p.h>
    4645#include <private/qgl_p.h>
    4746#include <private/qpaintengine_opengl_p.h>
     
    4948#include "qcolormap.h"
    5049#include <QDebug>
     50#include <QPixmap>
    5151
    5252
    5353QT_BEGIN_NAMESPACE
    5454
    55 
    56 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config,
    57                              const QX11Info &x11Info, bool useArgbVisual);
    5855
    5956/*
     
    8077    int screen = 0;
    8178
    82     d->display = eglGetDisplay(EGLNativeDisplayType(X11->display));
    83 
    84     if (!eglInitialize(d->display, NULL, NULL)) {
    85         qWarning("QGLTemporaryContext: Unable to initialize EGL display.");
    86         return;
    87     }
     79    d->display = QEgl::display();
    8880
    8981    EGLConfig config;
     
    10698    XVisualInfo *vi;
    10799    int numVisuals;
    108     EGLint id = 0;
    109 
    110     eglGetConfigAttrib(d->display, config, EGL_NATIVE_VISUAL_ID, &id);
    111     if (id == 0) {
    112         // EGL_NATIVE_VISUAL_ID is optional and might not be supported
    113         // on some implementations - we'll have to do it the hard way
    114         QX11Info xinfo;
    115         qt_egl_setup_x11_visual(visualInfo, d->display, config, xinfo, false);
    116     } else {
    117         visualInfo.visualid = id;
    118     }
     100
     101    visualInfo.visualid = QEgl::getCompatibleVisualId(config);
    119102    vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
    120103    if (!vi || numVisuals < 1) {
     
    171154}
    172155
    173 void qt_egl_add_platform_config(QEglProperties& props, QPaintDevice *device)
    174 {
    175     if (device->devType() == QInternal::Image)
    176         props.setPixelFormat(static_cast<QImage *>(device)->format());
    177 }
    178 
    179156// Chooses the EGL config and creates the EGL context
    180157bool QGLContext::chooseContext(const QGLContext* shareContext)
     
    187164    int devType = device()->devType();
    188165
    189     // Get the display and initialize it.
     166    QX11PixmapData *x11PixmapData = 0;
     167    if (devType == QInternal::Pixmap) {
     168        QPixmapData *pmd = static_cast<QPixmap*>(device())->data_ptr().data();
     169        if (pmd->classId() == QPixmapData::X11Class)
     170            x11PixmapData = static_cast<QX11PixmapData*>(pmd);
     171        else {
     172            // TODO: Replace the pixmap's data with a new QX11PixmapData
     173            qWarning("WARNING: Creating a QGLContext on a QPixmap is only supported for X11 pixmap backend");
     174            return false;
     175        }
     176    } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
     177        qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
     178        return false;
     179    }
     180
     181    // Only create the eglContext if we don't already have one:
    190182    if (d->eglContext == 0) {
    191183        d->eglContext = new QEglContext();
     184        d->ownsEglContext = true;
    192185        d->eglContext->setApi(QEgl::OpenGL);
     186
     187        // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
     188        // has the alpha channel option set:
     189        if (devType == QInternal::Widget) {
     190            QWidget* widget = static_cast<QWidget*>(device());
     191            if (widget->testAttribute(Qt::WA_TranslucentBackground))
     192                d->glFormat.setAlpha(true);
     193        }
    193194
    194195        // Construct the configuration we need for this surface.
    195196        QEglProperties configProps;
    196         qt_egl_set_format(configProps, devType, d->glFormat);
    197         qt_egl_add_platform_config(configProps, device());
     197        configProps.setDeviceType(devType);
    198198        configProps.setRenderableType(QEgl::OpenGL);
    199 
    200 #if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
    201         if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
    202             qDebug("Setting EGL_BUFFER_SIZE to 16");
    203             configProps.setValue(EGL_BUFFER_SIZE, 16);
    204             configProps.setValue(EGL_ALPHA_SIZE, 0);
    205         }
     199        qt_eglproperties_set_glformat(configProps, d->glFormat);
     200
     201        // Set buffer preserved for regular QWidgets, QGLWidgets are ok with either preserved or destroyed:
     202        if ((devType == QInternal::Widget) && qobject_cast<QGLWidget*>(static_cast<QWidget*>(device())) == 0)
     203            configProps.setValue(EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
    206204
    207205        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
     
    210208            return false;
    211209        }
    212 #else
    213         QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
    214         if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
    215             configProps.setValue(EGL_RED_SIZE, 5);
    216             configProps.setValue(EGL_GREEN_SIZE, 6);
    217             configProps.setValue(EGL_BLUE_SIZE, 5);
    218             configProps.setValue(EGL_ALPHA_SIZE, 0);
    219             matchType = QEgl::ExactPixelFormat;
    220         }
    221 
    222         // Search for a matching configuration, reducing the complexity
    223         // each time until we get something that matches.
    224         if (!d->eglContext->chooseConfig(configProps, matchType)) {
     210
     211        // Create a new context for the configuration.
     212        QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
     213        if (!d->eglContext->createContext(eglSharedContext)) {
    225214            delete d->eglContext;
    226215            d->eglContext = 0;
    227216            return false;
    228217        }
    229 #endif
    230 
    231 //        qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
    232 //        qDebug() << QEglProperties(d->eglContext->config()).toString();
    233 
    234         // Create a new context for the configuration.
    235         if (!d->eglContext->createContext
    236                 (shareContext ? shareContext->d_func()->eglContext : 0)) {
    237             delete d->eglContext;
    238             d->eglContext = 0;
    239             return false;
    240         }
    241218        d->sharing = d->eglContext->isSharing();
    242219        if (d->sharing && shareContext)
    243220            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
    244 
    245 #if defined(EGL_VERSION_1_1)
    246         if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
    247             eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
    248 #endif
    249     }
    250 
    251     // Inform the higher layers about the actual format properties.
    252     qt_egl_update_format(*(d->eglContext), d->glFormat);
     221    }
     222
     223    // Inform the higher layers about the actual format properties
     224    qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
     225
     226    // Do don't create the EGLSurface for everything.
     227    //    QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
     228    //    QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
     229    //    QPixmap - yes, create the EGLSurface but store it in QX11PixmapData::gl_surface
     230    //    QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf
     231
     232    if (devType == QInternal::Widget) {
     233        if (d->eglSurface != EGL_NO_SURFACE)
     234            eglDestroySurface(d->eglContext->display(), d->eglSurface);
     235        d->eglSurface = QEgl::createSurface(device(), d->eglContext->config());
     236        XFlush(X11->display);
     237        setWindowCreated(true);
     238    }
     239
     240    if (x11PixmapData) {
     241        // TODO: Actually check to see if the existing surface can be re-used
     242        if (x11PixmapData->gl_surface)
     243            eglDestroySurface(d->eglContext->display(), (EGLSurface)x11PixmapData->gl_surface);
     244
     245        x11PixmapData->gl_surface = (void*)QEgl::createSurface(device(), d->eglContext->config());
     246    }
    253247
    254248    return true;
     
    282276}
    283277
    284 //#define QT_DEBUG_X11_VISUAL_SELECTION 1
    285 
    286 bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
    287 {
    288     bool foundVisualIsArgb = useArgbVisual;
    289 
    290 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    291     qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
    292 #endif
    293 
    294     memset(&vi, 0, sizeof(XVisualInfo));
    295 
    296     EGLint eglConfigColorSize;
    297     eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
    298 
    299     // Check to see if EGL is suggesting an appropriate visual id:
    300     EGLint nativeVisualId;
    301     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
    302     vi.visualid = nativeVisualId;
    303 
    304     if (vi.visualid) {
    305         // EGL has suggested a visual id, so get the rest of the visual info for that id:
    306         XVisualInfo *chosenVisualInfo;
    307         int matchingCount = 0;
    308         chosenVisualInfo = XGetVisualInfo(x11Info.display(), VisualIDMask, &vi, &matchingCount);
    309         if (chosenVisualInfo) {
    310 #if !defined(QT_NO_XRENDER)
    311             if (useArgbVisual) {
    312                 // Check to make sure the visual provided by EGL is ARGB
    313                 XRenderPictFormat *format;
    314                 format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
    315                 if (format->type == PictTypeDirect && format->direct.alphaMask) {
    316 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    317                     qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
    318 #endif
    319                     foundVisualIsArgb = true;
    320                     vi = *chosenVisualInfo;
    321                 }
    322                 else {
    323                     qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
    324                              nativeVisualId, (int)config);
    325                     vi.visualid = 0;
    326                 }
    327             } else
    328 #endif
    329             {
    330                 if (eglConfigColorSize == chosenVisualInfo->depth) {
    331 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    332                     qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
    333 #endif
    334                     vi = *chosenVisualInfo;
    335                 } else
    336                     qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
    337                              nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
    338             }
    339             XFree(chosenVisualInfo);
    340         }
    341         else {
    342             qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
    343                      nativeVisualId, (int)config);
    344             vi.visualid = 0;
    345         }
    346     }
    347 
    348     // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
    349     // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
    350 
    351 #if !defined(QT_NO_XRENDER)
    352     if (vi.visualid == 0 && useArgbVisual) {
    353         // Try to use XRender to find an ARGB visual we can use
    354         vi.screen  = x11Info.screen();
    355         vi.depth   = 32; //### We might at some point (soon) get ARGB4444
    356         vi.c_class = TrueColor;
    357         XVisualInfo *matchingVisuals;
    358         int matchingCount = 0;
    359         matchingVisuals = XGetVisualInfo(x11Info.display(),
    360                                          VisualScreenMask|VisualDepthMask|VisualClassMask,
    361                                          &vi, &matchingCount);
    362 
    363         for (int i = 0; i < matchingCount; ++i) {
    364             XRenderPictFormat *format;
    365             format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
    366             if (format->type == PictTypeDirect && format->direct.alphaMask) {
    367                 vi = matchingVisuals[i];
    368                 foundVisualIsArgb = true;
    369 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    370                 qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
    371 #endif
    372                 break;
    373             }
    374         }
    375         XFree(matchingVisuals);
    376     }
    377 #endif
    378 
    379     if (vi.visualid == 0) {
    380         EGLint depth;
    381         eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &depth);
    382         int err;
    383         err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
    384         if (err == 0) {
    385             qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!",
    386                      (int)config, depth);
    387             depth = x11Info.depth();
    388             err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
    389             if (err == 0) {
    390                 qWarning("Error: Couldn't get any matching X visual!");
    391                 return false;
    392             } else
    393                 qWarning("         - Falling back to X11 suggested depth (%d)", depth);
    394         }
    395 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    396         else
    397             qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
    398 #endif
    399 
    400         // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
    401         if (useArgbVisual)
    402             foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
    403     }
    404 
    405 #ifdef QT_DEBUG_X11_VISUAL_SELECTION
    406     qDebug("Visual Info:");
    407     qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
    408     qDebug("   red_mask=0x%x", vi.red_mask);
    409     qDebug("   green_mask=0x%x", vi.green_mask);
    410     qDebug("   blue_mask=0x%x", vi.blue_mask);
    411     qDebug("   colormap_size=%d", vi.colormap_size);
    412     qDebug("   c_class=%d", vi.c_class);
    413     qDebug("   depth=%d", vi.depth);
    414     qDebug("   screen=%d", vi.screen);
    415     qDebug("   visualid=%d", vi.visualid);
    416 #endif
    417     return foundVisualIsArgb;
    418 }
    419 
    420278void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
    421279{
     
    434292    QGLContext* oldcx = d->glcx;
    435293    d->glcx = context;
    436 
    437     if (parentWidget()) {
    438         // force creation of delay-created widgets
    439         parentWidget()->winId();
    440         if (parentWidget()->x11Info().screen() != x11Info().screen())
    441             d_func()->xinfo = parentWidget()->d_func()->xinfo;
    442     }
    443 
    444     // If the application has set WA_TranslucentBackground and not explicitly set
    445     // the alpha buffer size to zero, modify the format so it have an alpha channel
    446     QGLFormat& fmt = d->glcx->d_func()->glFormat;
    447     const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
    448     if (tryArgbVisual && fmt.alphaBufferSize() == -1)
    449         fmt.setAlphaBufferSize(1);
    450294
    451295    bool createFailed = false;
     
    462306    }
    463307
    464     if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
    465         if (deleteOldContext)
    466             delete oldcx;
    467         return;
    468     }
    469 
    470     bool visible = isVisible();
    471     if (visible)
    472         hide();
    473 
    474     XVisualInfo vi;
    475     QEglContext *eglContext = d->glcx->d_func()->eglContext;
    476     bool usingArgbVisual = qt_egl_setup_x11_visual(vi, eglContext->display(), eglContext->config(),
    477                                                    x11Info(), tryArgbVisual);
    478 
    479     XSetWindowAttributes a;
    480 
    481     Window p = RootWindow(x11Info().display(), x11Info().screen());
    482     if (parentWidget())
    483         p = parentWidget()->winId();
    484 
    485     QColormap colmap = QColormap::instance(vi.screen);
    486     a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
    487     a.border_pixel = colmap.pixel(Qt::black);
    488 
    489     unsigned int valueMask = CWBackPixel|CWBorderPixel;
    490     if (usingArgbVisual) {
    491         a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone);
    492         valueMask |= CWColormap;
    493     }
    494 
    495     Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(),
    496                              0, vi.depth, InputOutput, vi.visual, valueMask, &a);
    497 
    498     if (deleteOldContext)
    499         delete oldcx;
    500     oldcx = 0;
    501 
    502     create(w); // Create with the ID of the window we've just created
    503 
    504 
    505     // Create the EGL surface to draw into.
    506     QGLContextPrivate *ctxpriv = d->glcx->d_func();
    507     ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(this);
    508     if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
    509         delete ctxpriv->eglContext;
    510         ctxpriv->eglContext = 0;
    511         return;
    512     }
    513 
    514     d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
    515 
    516     if (visible)
    517         show();
    518 
    519     XFlush(X11->display);
    520     d->glcx->setWindowCreated(true);
     308
     309    d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for
    521310}
    522311
     
    527316    initContext(context, shareWidget);
    528317
    529     if(q->isValid() && glcx->format().hasOverlay()) {
     318    if (q->isValid() && glcx->format().hasOverlay()) {
    530319        //no overlay
    531320        qWarning("QtOpenGL ES doesn't currently support overlays");
     
    546335}
    547336
    548 // Re-creates the EGL surface if the window ID has changed or if force is true
    549 void QGLWidgetPrivate::recreateEglSurface(bool force)
     337// Re-creates the EGL surface if the window ID has changed or if there isn't a surface
     338void QGLWidgetPrivate::recreateEglSurface()
    550339{
    551340    Q_Q(QGLWidget);
     
    553342    Window currentId = q->winId();
    554343
    555     if ( force || (currentId != eglSurfaceWindowId) ) {
    556         // The window id has changed so we need to re-create the EGL surface
    557         QEglContext *ctx = glcx->d_func()->eglContext;
    558         EGLSurface surface = glcx->d_func()->eglSurface;
    559         if (surface != EGL_NO_SURFACE)
    560             ctx->destroySurface(surface); // Will force doneCurrent() if nec.
    561         surface = ctx->createSurface(q);
    562         if (surface == EGL_NO_SURFACE)
    563             qWarning("Error creating EGL window surface: 0x%x", eglGetError());
    564         glcx->d_func()->eglSurface = surface;
    565 
     344    // If the window ID has changed since the surface was created, we need to delete the
     345    // old surface before re-creating a new one. Note: This should not be the case as the
     346    // surface should be deleted before the old window id.
     347    if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) {
     348        qWarning("EGL surface for deleted window %x was not destroyed", uint(eglSurfaceWindowId));
     349        glcx->d_func()->destroyEglSurfaceForDevice();
     350    }
     351
     352    if (glcx->d_func()->eglSurface == EGL_NO_SURFACE) {
     353        glcx->d_func()->eglSurface = glcx->d_func()->eglContext->createSurface(q);
    566354        eglSurfaceWindowId = currentId;
    567355    }
    568356}
    569357
    570 // Selects which configs should be used
    571 EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly)
    572 {
    573     // Cache the configs we select as they wont change:
    574     static EGLConfig roPixmapRGBConfig = 0;
    575     static EGLConfig roPixmapRGBAConfig = 0;
    576     static EGLConfig rwPixmapRGBConfig = 0;
    577     static EGLConfig rwPixmapRGBAConfig = 0;
    578 
    579     EGLConfig* targetConfig;
    580 
    581     if (hasAlpha) {
    582         if (readOnly)
    583             targetConfig = &roPixmapRGBAConfig;
    584         else
    585             targetConfig = &rwPixmapRGBAConfig;
    586     }
    587     else {
    588         if (readOnly)
    589             targetConfig = &roPixmapRGBConfig;
    590         else
    591             targetConfig = &rwPixmapRGBConfig;
    592     }
    593 
    594     if (*targetConfig == 0) {
    595         QEglProperties configAttribs;
    596         configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
    597         configAttribs.setRenderableType(QEgl::OpenGL);
    598         if (hasAlpha)
    599             configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
    600         else
    601             configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
    602 
    603         // If this is going to be a render target, it needs to have a depth, stencil & sample buffer
    604         if (!readOnly) {
    605             configAttribs.setValue(EGL_DEPTH_SIZE, 1);
    606             configAttribs.setValue(EGL_STENCIL_SIZE, 1);
    607             configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
    608         }
    609 
    610         EGLint configCount = 0;
    611         do {
    612             eglChooseConfig(QEglContext::display(), configAttribs.properties(), targetConfig, 1, &configCount);
    613             if (configCount > 0) {
    614                 // Got one
    615                 qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
    616                          << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
    617 
    618 //                QEglProperties configProps(*targetConfig);
    619 //                qDebug() << configProps.toString();
    620                 break;
    621             }
    622             qWarning("choosePixmapConfig() - No suitible config found, reducing requirements");
    623         } while (configAttribs.reduceConfiguration());
    624     }
    625 
    626     if (*targetConfig == 0)
    627         qWarning("choosePixmapConfig() - Couldn't find a suitable config");
    628 
    629     return *targetConfig;
    630 }
    631 
    632 bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly)
    633 {
    634     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
    635     QX11PixmapData* pixmapData = static_cast<QX11PixmapData*>(pmd);
    636 
    637     bool hasAlpha = pixmapData->hasAlphaChannel();
    638 
    639     EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly);
    640 
    641     QEglProperties pixmapAttribs;
    642 
    643     // If the pixmap can't be bound to a texture, it's pretty useless
    644     pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
    645     if (hasAlpha)
    646         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
    647     else
    648         pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
    649 
    650     EGLSurface pixmapSurface;
    651     pixmapSurface = eglCreatePixmapSurface(QEglContext::display(),
    652                                            pixmapConfig,
    653                                            (EGLNativePixmapType) pixmapData->handle(),
    654                                            pixmapAttribs.properties());
    655 //    qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
    656 //           pixmapSurface, pixmapData->handle());
    657     if (pixmapSurface == EGL_NO_SURFACE) {
    658         qWarning() << "Failed to create a pixmap surface using config" << (int)pixmapConfig
    659                    << ":" << QEglContext::errorString(eglGetError());
    660         return false;
    661     }
    662 
    663     static bool doneOnce = false;
    664     if (!doneOnce) {
    665         // Make sure QGLTextureCache is instanciated so it can install cleanup hooks
    666         // which cleanup the EGL surface.
    667         QGLTextureCache::instance();
    668         doneOnce = true;
    669     }
    670 
    671     Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
    672     pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
    673     QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
    674 
    675     return true;
    676 }
    677 
    678 
    679 QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key,
     358
     359QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key,
    680360                                                           QGLContext::BindOptions options)
    681361{
     
    686366        return 0;
    687367
    688     Q_ASSERT(pd->classId() == QPixmapData::X11Class);
    689368
    690369    static bool checkedForTFP = false;
    691370    static bool haveTFP = false;
     371    static bool checkedForEglImageTFP = false;
     372    static bool haveEglImageTFP = false;
     373
     374
     375    if (!checkedForEglImageTFP) {
     376        checkedForEglImageTFP = true;
     377
     378        // We need to be able to create an EGLImage from a native pixmap, which was split
     379        // into a separate EGL extension, EGL_KHR_image_pixmap. It is possible to have
     380        // eglCreateImageKHR & eglDestroyImageKHR without support for pixmaps, so we must
     381        // check we have the EGLImage from pixmap functionality.
     382        if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) {
     383
     384            // Being able to create an EGLImage from a native pixmap is also pretty useless
     385            // without the ability to bind that EGLImage as a texture, which is provided by
     386            // the GL_OES_EGL_image extension, which we try to resolve here:
     387            haveEglImageTFP = qt_resolve_eglimage_gl_extensions(q);
     388
     389            if (haveEglImageTFP)
     390                qDebug("Found EGL_KHR_image_pixmap & GL_OES_EGL_image extensions (preferred method)!");
     391        }
     392    }
    692393
    693394    if (!checkedForTFP) {
    694395        // Check for texture_from_pixmap egl extension
    695396        checkedForTFP = true;
    696         if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
    697             eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
     397        if (QEgl::hasExtension("EGL_NOKIA_texture_from_pixmap") ||
     398            QEgl::hasExtension("EGL_EXT_texture_from_pixmap"))
    698399        {
    699400            qDebug("Found texture_from_pixmap EGL extension!");
     
    702403    }
    703404
    704     if (!haveTFP)
     405    if (!haveTFP && !haveEglImageTFP)
    705406        return 0;
    706407
    707     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
    708 
     408
     409    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
     410    Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
    709411    bool hasAlpha = pixmapData->hasAlphaChannel();
    710 
    711     // Check to see if the surface is still valid
    712     if (pixmapData->gl_surface &&
    713         hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
    714     {
    715         // Surface is invalid!
    716         destroyGlSurfaceForPixmap(pixmapData);
    717     }
    718 
    719     if (pixmapData->gl_surface == 0) {
    720         bool success = qt_createEGLSurfaceForPixmap(pixmapData, true);
    721         if (!success) {
    722             haveTFP = false;
    723             return 0;
    724         }
    725     }
    726 
    727     Q_ASSERT(pixmapData->gl_surface);
    728 
     412    bool pixmapHasValidSurface = false;
     413    bool textureIsBound = false;
    729414    GLuint textureId;
    730415    glGenTextures(1, &textureId);
    731416    glBindTexture(GL_TEXTURE_2D, textureId);
    732417
    733     // bind the egl pixmap surface to a texture
    734     EGLBoolean success;
    735     success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
    736     if (success == EGL_FALSE) {
    737         qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
    738         eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface);
    739         pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
    740         haveTFP = false;
    741         return 0;
    742     }
    743 
    744     QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
    745     pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
    746 
    747     // We assume the cost of bound pixmaps is zero
    748     QGLTextureCache::instance()->insert(q, key, texture, 0);
    749 
    750     glBindTexture(GL_TEXTURE_2D, textureId);
     418    if (haveTFP && pixmapData->gl_surface &&
     419        hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
     420    {
     421        pixmapHasValidSurface = true;
     422    }
     423
     424    // If we already have a valid EGL surface for the pixmap, we should use it
     425    if (pixmapHasValidSurface) {
     426        EGLBoolean success;
     427        success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
     428        if (success == EGL_FALSE) {
     429            qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
     430            eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
     431            pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
     432        } else
     433            textureIsBound = true;
     434    }
     435
     436    // If the pixmap doesn't already have a valid surface, try binding it via EGLImage
     437    // first, as going through EGLImage should be faster and better supported:
     438    if (!textureIsBound && haveEglImageTFP) {
     439        EGLImageKHR eglImage;
     440
     441        EGLint attribs[] = {
     442            EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
     443            EGL_NONE
     444        };
     445        eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
     446                                     (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs);
     447
     448        QGLContext* ctx = q;
     449        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
     450
     451        GLint err = glGetError();
     452        if (err == GL_NO_ERROR)
     453            textureIsBound = true;
     454
     455        // Once the egl image is bound, the texture becomes a new sibling image and we can safely
     456        // destroy the EGLImage we created for the pixmap:
     457        if (eglImage != EGL_NO_IMAGE_KHR)
     458            QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
     459    }
     460
     461    if (!textureIsBound && haveTFP) {
     462        // Check to see if the surface is still valid
     463        if (pixmapData->gl_surface &&
     464            hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
     465        {
     466            // Surface is invalid!
     467            destroyGlSurfaceForPixmap(pixmapData);
     468        }
     469
     470        if (pixmapData->gl_surface == 0) {
     471            EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap,
     472                                                   QEgl::OpenGL,
     473                                                   hasAlpha ? QEgl::Translucent : QEgl::NoOptions);
     474
     475            pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config);
     476            if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE)
     477                return false;
     478        }
     479
     480        EGLBoolean success;
     481        success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
     482        if (success == EGL_FALSE) {
     483            qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
     484            eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
     485            pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
     486            haveTFP = false; // If TFP isn't working, disable it's use
     487        } else
     488            textureIsBound = true;
     489    }
     490
     491    QGLTexture *texture = 0;
     492
     493    if (textureIsBound) {
     494        texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
     495        pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
     496
     497        // We assume the cost of bound pixmaps is zero
     498        QGLTextureCache::instance()->insert(q, key, texture, 0);
     499
     500        glBindTexture(GL_TEXTURE_2D, textureId);
     501    } else
     502        glDeleteTextures(1, &textureId);
     503
    751504    return texture;
    752505}
     506
    753507
    754508void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
     
    758512    if (pixmapData->gl_surface) {
    759513        EGLBoolean success;
    760         success = eglDestroySurface(QEglContext::display(), (EGLSurface)pixmapData->gl_surface);
     514        success = eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
    761515        if (success == EGL_FALSE) {
    762516            qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
    763                        << QEglContext::errorString(eglGetError());
     517                       << QEgl::errorString();
    764518        }
    765519        pixmapData->gl_surface = 0;
     
    773527    if (pixmapData->gl_surface) {
    774528        EGLBoolean success;
    775         success = eglReleaseTexImage(QEglContext::display(),
     529        success = eglReleaseTexImage(QEgl::display(),
    776530                                     (EGLSurface)pixmapData->gl_surface,
    777531                                     EGL_BACK_BUFFER);
    778532        if (success == EGL_FALSE) {
    779533            qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
    780                        << QEglContext::errorString(eglGetError());
     534                       << QEgl::errorString();
    781535        }
    782536    }
  • trunk/src/opengl/qglcolormap.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglcolormap.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglextensions.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    192192bool qt_resolve_buffer_extensions(QGLContext *ctx)
    193193{
    194     if (glMapBufferARB && glUnmapBufferARB
    195 #if !defined(QT_OPENGL_ES_2)
    196         && glBindBuffer && glDeleteBuffers && glGenBuffers && glBufferData
    197 #endif
    198         )
    199         return true;
    200 
    201 #if !defined(QT_OPENGL_ES_2)
     194#if defined(QGL_RESOLVE_BUFFER_FUNCS)
     195    if (glBindBuffer && glDeleteBuffers && glGenBuffers && glBufferData
     196            && glBufferSubData && glGetBufferParameteriv)
     197        return true;
     198#endif
     199
     200#if defined(QGL_RESOLVE_BUFFER_FUNCS)
    202201    glBindBuffer = (_glBindBuffer) qt_gl_getProcAddressARB(ctx, "glBindBuffer");
    203202    glDeleteBuffers = (_glDeleteBuffers) qt_gl_getProcAddressARB(ctx, "glDeleteBuffers");
    204203    glGenBuffers = (_glGenBuffers) qt_gl_getProcAddressARB(ctx, "glGenBuffers");
    205204    glBufferData = (_glBufferData) qt_gl_getProcAddressARB(ctx, "glBufferData");
     205    glBufferSubData = (_glBufferSubData) qt_gl_getProcAddressARB(ctx, "glBufferSubData");
     206    glGetBufferSubData = (_glGetBufferSubData) qt_gl_getProcAddressARB(ctx, "glGetBufferSubData");
     207    glGetBufferParameteriv = (_glGetBufferParameteriv) qt_gl_getProcAddressARB(ctx, "glGetBufferParameteriv");
    206208#endif
    207209    glMapBufferARB = (_glMapBufferARB) qt_gl_getProcAddressARB(ctx, "glMapBuffer");
    208210    glUnmapBufferARB = (_glUnmapBufferARB) qt_gl_getProcAddressARB(ctx, "glUnmapBuffer");
    209211
    210     return glMapBufferARB
    211         && glUnmapBufferARB
    212 #if !defined(QT_OPENGL_ES_2)
    213         && glBindBuffer
     212#if defined(QGL_RESOLVE_BUFFER_FUNCS)
     213    return glBindBuffer
    214214        && glDeleteBuffers
    215215        && glGenBuffers
    216216        && glBufferData
    217 #endif
    218         ;
    219 }
     217        && glBufferSubData
     218        && glGetBufferParameteriv;
     219        // glGetBufferSubData() is optional
     220#else
     221    return true;
     222#endif
     223}
     224
     225#ifndef QT_NO_EGL
     226bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx)
     227{
     228    if (glEGLImageTargetTexture2DOES || glEGLImageTargetRenderbufferStorageOES)
     229        return true;
     230    glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetTexture2DOES"));
     231    glEGLImageTargetRenderbufferStorageOES = (_glEGLImageTargetRenderbufferStorageOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetRenderbufferStorageOES"));
     232    return glEGLImageTargetTexture2DOES && glEGLImageTargetRenderbufferStorageOES;
     233}
     234#endif
    220235
    221236bool qt_resolve_glsl_extensions(QGLContext *ctx)
    222237{
     238
    223239#if defined(QT_OPENGL_ES_2)
    224240    // The GLSL shader functions are always present in OpenGL/ES 2.0.
     
    233249    if (glCreateShader)
    234250        return true;
     251
     252    // Geometry shaders are optional...
     253    glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT"));
     254    glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT"));
     255    glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
     256    glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
     257
     258    // Must at least have the FragmentShader extension to continue.
     259    if (!(QGLExtensions::glExtensions() & QGLExtensions::FragmentShader))
     260        return false;
    235261
    236262    glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
  • trunk/src/opengl/qglextensions_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6969#endif
    7070
     71#ifndef QT_NO_EGL
     72// Needed for EGLImageKHR definition:
     73#include <QtGui/private/qegl_p.h>
     74#endif
     75
    7176#include <QtCore/qglobal.h>
    7277
    7378#ifndef GL_ARB_vertex_buffer_object
     79typedef ptrdiff_t GLintptrARB;
    7480typedef ptrdiff_t GLsizeiptrARB;
    7581#endif
     
    7985#endif
    8086
    81 // ARB_pixel_buffer_object
     87// ARB_vertex_buffer_object
    8288typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint);
    8389typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *);
    8490typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *);
    8591typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
     92typedef void (APIENTRY *_glBufferSubData) (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);
     93typedef void (APIENTRY *_glGetBufferSubData) (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);
     94typedef void (APIENTRY *_glGetBufferParameteriv) (GLenum, GLenum, GLint *);
    8695typedef GLvoid* (APIENTRY *_glMapBufferARB) (GLenum, GLenum);
    8796typedef GLboolean (APIENTRY *_glUnmapBufferARB) (GLenum);
     97// We can call the buffer functions directly in OpenGL/ES 1.1 or higher,
     98// but all other platforms need to resolve the extensions.
     99#if defined(QT_OPENGL_ES)
     100#if defined(GL_OES_VERSION_1_0) && !defined(GL_OES_VERSION_1_1)
     101#define QGL_RESOLVE_BUFFER_FUNCS 1
     102#endif
     103#else
     104#define QGL_RESOLVE_BUFFER_FUNCS 1
     105#endif
    88106
    89107// ARB_fragment_program
     
    185203                                                               GLenum internalformat, GLsizei width, GLsizei height);
    186204
     205// GL_EXT_geometry_shader4
     206typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value);
     207typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment,
     208                                                  GLuint texture, GLint level);
     209typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment,
     210                                                       GLuint texture, GLint level, GLint layer);
     211typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment,
     212                                                      GLuint texture, GLint level, GLenum face);
     213
    187214// ARB_texture_compression
    188215typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
    189216                                                     GLsizei, GLint, GLsizei, const GLvoid *);
     217
     218#ifndef QT_NO_EGL
     219// OES_EGL_image
     220// Note: We define these to take EGLImage whereas spec says they take a new GLeglImageOES
     221//       type, which the EGL image should be cast to.
     222typedef void (APIENTRY *_glEGLImageTargetTexture2DOES) (GLenum, EGLImageKHR);
     223typedef void (APIENTRY *_glEGLImageTargetRenderbufferStorageOES) (GLenum, EGLImageKHR);
     224#endif
    190225
    191226QT_BEGIN_NAMESPACE
     
    286321
    287322        // Buffer objects:
    288 #if !defined(QT_OPENGL_ES_2)
     323#if defined(QGL_RESOLVE_BUFFER_FUNCS)
    289324        qt_glBindBuffer = 0;
    290325        qt_glDeleteBuffers = 0;
    291326        qt_glGenBuffers = 0;
    292327        qt_glBufferData = 0;
     328        qt_glBufferSubData = 0;
     329        qt_glGetBufferSubData = 0;
     330        qt_glGetBufferParameteriv = 0;
    293331#endif
    294332        qt_glMapBufferARB = 0;
    295333        qt_glUnmapBufferARB = 0;
    296334
     335        qt_glProgramParameteriEXT = 0;
     336        qt_glFramebufferTextureEXT = 0;
     337        qt_glFramebufferTextureLayerEXT = 0;
     338        qt_glFramebufferTextureFaceEXT = 0;
    297339#if !defined(QT_OPENGL_ES)
    298340        // Texture compression
    299341        qt_glCompressedTexImage2DARB = 0;
     342#endif
     343
     344#ifndef QT_NO_EGL
     345        // OES_EGL_image
     346        qt_glEGLImageTargetTexture2DOES = 0;
     347        qt_glEGLImageTargetRenderbufferStorageOES = 0;
    300348#endif
    301349    }
     
    398446
    399447    // Buffer objects
    400 #if !defined(QT_OPENGL_ES_2)
     448#if defined(QGL_RESOLVE_BUFFER_FUNCS)
    401449    _glBindBuffer qt_glBindBuffer;
    402450    _glDeleteBuffers qt_glDeleteBuffers;
    403451    _glGenBuffers qt_glGenBuffers;
    404452    _glBufferData qt_glBufferData;
     453    _glBufferSubData qt_glBufferSubData;
     454    _glGetBufferSubData qt_glGetBufferSubData;
     455    _glGetBufferParameteriv qt_glGetBufferParameteriv;
    405456#endif
    406457    _glMapBufferARB qt_glMapBufferARB;
    407458    _glUnmapBufferARB qt_glUnmapBufferARB;
    408459
     460    // Geometry shaders...
     461    _glProgramParameteriEXT qt_glProgramParameteriEXT;
     462    _glFramebufferTextureEXT qt_glFramebufferTextureEXT;
     463    _glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT;
     464    _glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT;
    409465#if !defined(QT_OPENGL_ES)
    410466    // Texture compression
    411467    _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
    412468#endif
     469
     470#ifndef QT_NO_EGL
     471    // OES_EGL_image
     472    _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES;
     473    _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES;
     474#endif
    413475};
    414476
    415477
    416478// OpenGL constants
     479
     480#ifndef GL_ARRAY_BUFFER
     481#define GL_ARRAY_BUFFER                   0x8892
     482#endif
     483
     484#ifndef GL_STATIC_DRAW
     485#define GL_STATIC_DRAW                    0x88E4
     486#endif
    417487
    418488/* NV_texture_rectangle */
     
    429499
    430500#ifndef GL_RGB16
    431 #define GL_RGB16 32852
     501#define GL_RGB16 0x8054
    432502#endif
    433503
    434504#ifndef GL_UNSIGNED_SHORT_5_6_5
    435 #define GL_UNSIGNED_SHORT_5_6_5 33635
     505#define GL_UNSIGNED_SHORT_5_6_5 0x8363
    436506#endif
    437507
     
    492562#ifndef GL_TEXTURE1
    493563#define GL_TEXTURE1 0x84C1
     564#endif
     565
     566#ifndef GL_DEPTH_COMPONENT16
     567#define GL_DEPTH_COMPONENT16 0x81A5
     568#endif
     569
     570#ifndef GL_DEPTH_COMPONENT24_OES
     571#define GL_DEPTH_COMPONENT24_OES 0x81A6
    494572#endif
    495573
     
    600678#endif
    601679
     680#ifndef GL_VERSION_1_5
     681#define GL_ARRAY_BUFFER                                         0x8892
     682#define GL_ELEMENT_ARRAY_BUFFER                                 0x8893
     683#define GL_STREAM_DRAW                                          0x88E0
     684#define GL_STREAM_READ                                          0x88E1
     685#define GL_STREAM_COPY                                          0x88E2
     686#define GL_STATIC_DRAW                                          0x88E4
     687#define GL_STATIC_READ                                          0x88E5
     688#define GL_STATIC_COPY                                          0x88E6
     689#define GL_DYNAMIC_DRAW                                         0x88E8
     690#define GL_DYNAMIC_READ                                         0x88E9
     691#define GL_DYNAMIC_COPY                                         0x88EA
     692#endif
     693
    602694#ifndef GL_VERSION_2_0
    603695#define GL_FRAGMENT_SHADER 0x8B30
     
    629721#endif
    630722
     723// Geometry shader defines
     724#ifndef GL_GEOMETRY_SHADER_EXT
     725#  define GL_GEOMETRY_SHADER_EXT 0x8DD9
     726#  define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
     727#  define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
     728#  define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
     729#  define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
     730#  define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
     731#  define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
     732#  define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
     733#  define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
     734#  define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
     735#  define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
     736#  define GL_LINES_ADJACENCY_EXT 0xA
     737#  define GL_LINE_STRIP_ADJACENCY_EXT 0xB
     738#  define GL_TRIANGLES_ADJACENCY_EXT 0xC
     739#  define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
     740#  define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
     741#  define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
     742#  define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
     743#  define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
     744#  define GL_PROGRAM_POINT_SIZE_EXT 0x8642
     745#endif
    631746
    632747#if !defined(QT_OPENGL_ES_2)
     
    668783
    669784// Buffer objects
    670 #if !defined(QT_OPENGL_ES_2)
     785#if defined(QGL_RESOLVE_BUFFER_FUNCS)
    671786#define glBindBuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindBuffer
    672787#define glDeleteBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteBuffers
    673788#define glGenBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenBuffers
    674789#define glBufferData QGLContextPrivate::extensionFuncs(ctx).qt_glBufferData
     790#define glBufferSubData QGLContextPrivate::extensionFuncs(ctx).qt_glBufferSubData
     791#define glGetBufferSubData QGLContextPrivate::extensionFuncs(ctx).qt_glGetBufferSubData
     792#define glGetBufferParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetBufferParameteriv
    675793#endif
    676794#define glMapBufferARB QGLContextPrivate::extensionFuncs(ctx).qt_glMapBufferARB
     
    746864#endif
    747865
     866#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT
     867#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT
     868#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT
     869#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT
     870
    748871#if !defined(QT_OPENGL_ES)
    749872#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
     873#endif
     874
     875#ifndef QT_NO_EGL
     876// OES_EGL_image
     877#define glEGLImageTargetTexture2DOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetTexture2DOES
     878#define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES
    750879#endif
    751880
     
    760889bool qt_resolve_glsl_extensions(QGLContext *ctx);
    761890
     891#ifndef QT_NO_EGL
     892Q_OPENGL_EXPORT bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx);
     893#endif
     894
    762895QT_END_NAMESPACE
    763896
  • trunk/src/opengl/qglframebufferobject.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545#include <qdebug.h>
    4646#include <private/qgl_p.h>
    47 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     47#if !defined(QT_OPENGL_ES_1)
    4848#include <private/qpaintengineex_opengl2_p.h>
    4949#endif
     
    5656#include <qlibrary.h>
    5757#include <qimage.h>
    58 
    59 #ifdef QT_OPENGL_ES_1_CL
    60 #include "qgl_cl_p.h"
    61 #endif
    6258
    6359QT_BEGIN_NAMESPACE
     
    133129    On OpenGL/ES systems, the default internal format is \c GL_RGBA.
    134130
    135     \sa samples(), attachment(), target(), internalTextureFormat()
     131    \sa samples(), attachment(), internalTextureFormat()
    136132*/
    137133
     
    450446        glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
    451447
    452         samples = qBound(1, int(samples), int(maxSamples));
     448        samples = qBound(0, int(samples), int(maxSamples));
    453449
    454450        glGenRenderbuffers(1, &color_buffer);
    455451        glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer);
    456         if (glRenderbufferStorageMultisampleEXT) {
     452        if (glRenderbufferStorageMultisampleEXT && samples > 0) {
    457453            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
    458454                internal_format, size.width(), size.height());
     
    473469    }
    474470
     471    // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
     472    // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
     473    // might not be supported while separate buffers are, according to QTBUG-12861.
     474
    475475    if (attachment == QGLFramebufferObject::CombinedDepthStencil
    476476        && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) {
    477477        // depth and stencil buffer needs another extension
    478         glGenRenderbuffers(1, &depth_stencil_buffer);
    479         Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
    480         glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    481         Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
     478        glGenRenderbuffers(1, &depth_buffer);
     479        Q_ASSERT(!glIsRenderbuffer(depth_buffer));
     480        glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer);
     481        Q_ASSERT(glIsRenderbuffer(depth_buffer));
    482482        if (samples != 0 && glRenderbufferStorageMultisampleEXT)
    483483            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     
    487487                GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
    488488
    489         GLint i = 0;
    490         glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
     489        stencil_buffer = depth_buffer;
    491490        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
    492                                      GL_RENDERBUFFER_EXT, depth_stencil_buffer);
     491                                     GL_RENDERBUFFER_EXT, depth_buffer);
    493492        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
    494                                      GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    495         fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
     493                                     GL_RENDERBUFFER_EXT, stencil_buffer);
    496494
    497495        valid = checkFramebufferStatus();
    498         if (!valid)
    499             glDeleteRenderbuffers(1, &depth_stencil_buffer);
    500     } else if (attachment == QGLFramebufferObject::Depth
    501                || attachment == QGLFramebufferObject::CombinedDepthStencil)
     496        if (!valid) {
     497            glDeleteRenderbuffers(1, &depth_buffer);
     498            stencil_buffer = depth_buffer = 0;
     499        }
     500    }
     501
     502    if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil
     503        || (attachment == QGLFramebufferObject::Depth)))
    502504    {
    503         glGenRenderbuffers(1, &depth_stencil_buffer);
    504         Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
    505         glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    506         Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
     505        glGenRenderbuffers(1, &depth_buffer);
     506        Q_ASSERT(!glIsRenderbuffer(depth_buffer));
     507        glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_buffer);
     508        Q_ASSERT(glIsRenderbuffer(depth_buffer));
    507509        if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
    508510#ifdef QT_OPENGL_ES
    509 #define GL_DEPTH_COMPONENT16 0x81A5
    510             glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
    511                 GL_DEPTH_COMPONENT16, size.width(), size.height());
     511            if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) {
     512                glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     513                    GL_DEPTH_COMPONENT24_OES, size.width(), size.height());
     514            } else {
     515                glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     516                    GL_DEPTH_COMPONENT16, size.width(), size.height());
     517            }
    512518#else
    513519            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     
    516522        } else {
    517523#ifdef QT_OPENGL_ES
    518 #define GL_DEPTH_COMPONENT16 0x81A5
    519             glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
     524            if (QGLExtensions::glExtensions() & QGLExtensions::Depth24) {
     525                glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_OES,
     526                                        size.width(), size.height());
     527            } else {
     528                glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
     529                                        size.width(), size.height());
     530            }
    520531#else
    521532            glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
    522533#endif
    523534        }
    524         GLint i = 0;
    525         glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
    526535        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
    527                                      GL_RENDERBUFFER_EXT, depth_stencil_buffer);
     536                                     GL_RENDERBUFFER_EXT, depth_buffer);
     537        valid = checkFramebufferStatus();
     538        if (!valid) {
     539            glDeleteRenderbuffers(1, &depth_buffer);
     540            depth_buffer = 0;
     541        }
     542    }
     543
     544    if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) {
     545        glGenRenderbuffers(1, &stencil_buffer);
     546        Q_ASSERT(!glIsRenderbuffer(stencil_buffer));
     547        glBindRenderbuffer(GL_RENDERBUFFER_EXT, stencil_buffer);
     548        Q_ASSERT(glIsRenderbuffer(stencil_buffer));
     549        if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
     550#ifdef QT_OPENGL_ES
     551            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     552                GL_STENCIL_INDEX8_EXT, size.width(), size.height());
     553#else
     554            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     555                GL_STENCIL_INDEX, size.width(), size.height());
     556#endif
     557        } else {
     558#ifdef QT_OPENGL_ES
     559            glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT,
     560                                  size.width(), size.height());
     561#else
     562            glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
     563                                  size.width(), size.height());
     564#endif
     565        }
     566        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
     567                                  GL_RENDERBUFFER_EXT, stencil_buffer);
     568        valid = checkFramebufferStatus();
     569        if (!valid) {
     570            glDeleteRenderbuffers(1, &stencil_buffer);
     571            stencil_buffer = 0;
     572        }
     573    }
     574
     575    // The FBO might have become valid after removing the depth or stencil buffer.
     576    valid = checkFramebufferStatus();
     577
     578    if (depth_buffer && stencil_buffer) {
     579        fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
     580    } else if (depth_buffer) {
    528581        fbo_attachment = QGLFramebufferObject::Depth;
    529         valid = checkFramebufferStatus();
    530         if (!valid)
    531             glDeleteRenderbuffers(1, &depth_stencil_buffer);
    532582    } else {
    533583        fbo_attachment = QGLFramebufferObject::NoAttachment;
     
    540590        else
    541591            glDeleteTextures(1, &texture);
     592        if (depth_buffer)
     593            glDeleteRenderbuffers(1, &depth_buffer);
     594        if (stencil_buffer && depth_buffer != stencil_buffer)
     595            glDeleteRenderbuffers(1, &stencil_buffer);
    542596        glDeleteFramebuffers(1, &fbo);
    543597        fbo_guard.setId(0);
     
    822876        if (d->color_buffer)
    823877            glDeleteRenderbuffers(1, &d->color_buffer);
    824         if (d->depth_stencil_buffer)
    825             glDeleteRenderbuffers(1, &d->depth_stencil_buffer);
     878        if (d->depth_buffer)
     879            glDeleteRenderbuffers(1, &d->depth_buffer);
     880        if (d->stencil_buffer && d->stencil_buffer != d->depth_buffer)
     881            glDeleteRenderbuffers(1, &d->stencil_buffer);
    826882        GLuint fbo = d->fbo();
    827883        glDeleteFramebuffers(1, &fbo);
     
    9881044}
    9891045
    990 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     1046#if !defined(QT_OPENGL_ES_1)
    9911047Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
    9921048#endif
     
    10031059        return d->engine;
    10041060
    1005 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     1061#if !defined(QT_OPENGL_ES_1)
    10061062#if !defined (QT_OPENGL_ES_2)
    10071063    if (qt_gl_preferGL2Engine()) {
     
    10291085
    10301086/*!
     1087    \fn bool QGLFramebufferObject::bindDefault()
     1088    \internal
     1089
     1090    Switches rendering back to the default, windowing system provided
     1091    framebuffer.
     1092    Returns true upon success, false otherwise.
     1093
     1094    \sa bind(), release()
     1095*/
     1096bool QGLFramebufferObject::bindDefault()
     1097{
     1098    QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
     1099
     1100    if (ctx) {
     1101        bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
     1102        if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
     1103            return false;
     1104
     1105        ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo;
     1106        glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->default_fbo);
     1107#ifdef QT_DEBUG
     1108    } else {
     1109        qWarning("QGLFramebufferObject::bindDefault() called without current context.");
     1110#endif
     1111    }
     1112
     1113    return ctx != 0;
     1114}
     1115
     1116/*!
    10311117    \fn bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
    10321118
     
    10861172#endif
    10871173
    1088 extern int qt_defaultDpiX();
    1089 extern int qt_defaultDpiY();
     1174Q_DECL_IMPORT extern int qt_defaultDpiX();
     1175Q_DECL_IMPORT extern int qt_defaultDpiY();
    10901176
    10911177/*! \reimp */
  • trunk/src/opengl/qglframebufferobject.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    109109    GLuint handle() const;
    110110
     111    static bool bindDefault();
     112
    111113    static bool hasOpenGLFramebufferObjects();
    112114
  • trunk/src/opengl/qglframebufferobject_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    127127{
    128128public:
    129     QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_stencil_buffer(0)
     129    QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0)
    130130                                  , color_buffer(0), valid(false), engine(0) {}
    131131    ~QGLFramebufferObjectPrivate() {}
     
    137137    QGLSharedResourceGuard fbo_guard;
    138138    GLuint texture;
    139     GLuint depth_stencil_buffer;
     139    GLuint depth_buffer;
     140    GLuint stencil_buffer;
    140141    GLuint color_buffer;
    141142    GLenum target;
  • trunk/src/opengl/qglpaintdevice.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4949#endif
    5050
    51 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     51#if !defined(QT_OPENGL_ES_1)
    5252#include <private/qpixmapdata_gl_p.h>
    53 #endif
    54 
    55 #if defined(QT_OPENGL_ES_1_CL)
    56 #include "qgl_cl_p.h"
    5753#endif
    5854
     
    6864}
    6965
     66int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
     67{
     68    switch(metric) {
     69    case PdmWidth:
     70        return size().width();
     71    case PdmHeight:
     72        return size().height();
     73    case PdmDepth: {
     74        const QGLFormat f = format();
     75        return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
     76    }
     77    default:
     78        qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
     79        return 0;
     80    }
     81}
    7082
    7183void QGLPaintDevice::beginPaint()
     
    164176            glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
    165177        }
    166         glClear(GL_COLOR_BUFFER_BIT);
     178        if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
     179            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
     180        else
     181            glClear(GL_COLOR_BUFFER_BIT);
    167182    }
    168183}
     
    204219            break;
    205220        case QInternal::Pixmap: {
    206 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     221#if !defined(QT_OPENGL_ES_1)
    207222            QPixmapData* pmd = static_cast<QPixmap*>(pd)->pixmapData();
    208223            if (pmd->classId() == QPixmapData::OpenGLClass)
  • trunk/src/opengl/qglpaintdevice_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8282
    8383protected:
     84    int metric(QPaintDevice::PaintDeviceMetric metric) const;
    8485    GLuint m_previousFBO;
    8586    GLuint m_thisFBO;
  • trunk/src/opengl/qglpixelbuffer.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6868       additional copy operations. This is supported only on Windows
    6969       and Mac OS X systems that provide the \c render_texture
    70        extension.
     70       extension. Note that under Windows, a multi-sampled pbuffer
     71       can't be used in conjunction with the \c render_texture
     72       extension. If a multi-sampled pbuffer is requested under
     73       Windows, the \c render_texture extension is turned off for that
     74       pbuffer.
     75
     76
    7177    \endlist
    7278
     
    7985#include <QtCore/qglobal.h>
    8086
    81 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     87#if !defined(QT_OPENGL_ES_1)
    8288#include <private/qpaintengineex_opengl2_p.h>
    8389#endif
     
    138144        qctx->d_func()->dc = dc;
    139145        qctx->d_func()->rc = ctx;
    140 #elif (defined(Q_WS_X11) && !defined(QT_OPENGL_ES))
     146#elif (defined(Q_WS_X11) && defined(QT_NO_EGL))
    141147        qctx->d_func()->cx = ctx;
    142148        qctx->d_func()->pbuf = (void *) pbuf;
     
    145151        qctx->d_func()->cx = ctx;
    146152        qctx->d_func()->vi = 0;
    147 #elif defined(QT_OPENGL_ES)
     153#elif !defined(QT_NO_EGL)
    148154        qctx->d_func()->eglContext = ctx;
    149155        qctx->d_func()->eglSurface = pbuf;
     
    255261*/
    256262
    257 #if (defined(Q_WS_X11) || defined(Q_WS_WIN)) && !defined(QT_OPENGL_ES)
     263#if (defined(Q_WS_X11) || defined(Q_WS_WIN)) && defined(QT_NO_EGL)
    258264GLuint QGLPixelBuffer::generateDynamicTexture() const
    259265{
     
    388394}
    389395
    390 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     396#if !defined(QT_OPENGL_ES_1)
    391397Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
    392398#endif
     
    399405QPaintEngine *QGLPixelBuffer::paintEngine() const
    400406{
    401 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     407#if defined(QT_OPENGL_ES_1)
    402408    return qt_buffer_engine();
    403409#elif defined(QT_OPENGL_ES_2)
     
    411417}
    412418
    413 extern int qt_defaultDpiX();
    414 extern int qt_defaultDpiY();
     419Q_DECL_IMPORT extern int qt_defaultDpiX();
     420Q_DECL_IMPORT extern int qt_defaultDpiY();
    415421
    416422/*! \reimp */
  • trunk/src/opengl/qglpixelbuffer.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    113113    friend class QGLPaintDevice;
    114114    friend class QGLPBufferGLPaintDevice;
     115    friend class QGLContextPrivate;
    115116};
    116117
  • trunk/src/opengl/qglpixelbuffer_egl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4848#include <private/qgl_p.h>
    4949
    50 #ifdef QT_OPENGL_ES_1_CL
    51 #include "qgl_cl_p.h"
    52 #endif
    53 
    5450QT_BEGIN_NAMESPACE
    5551
     
    7975        ctx->setConfig(shareContext->config());
    8076#if QGL_RENDER_TEXTURE
    81         EGLint value = EGL_FALSE;
    82         if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA, &value) && value)
     77        if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA) == EGL_TRUE)
    8378            textureFormat = EGL_TEXTURE_RGBA;
    84         else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB, &value) && value)
     79        else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB) == EGL_TRUE)
    8580            textureFormat = EGL_TEXTURE_RGB;
    8681#endif
    8782    } else {
    8883        QEglProperties configProps;
    89         qt_egl_set_format(configProps, QInternal::Pbuffer, f);
     84        qt_eglproperties_set_glformat(configProps, f);
     85        configProps.setDeviceType(QInternal::Pbuffer);
    9086        configProps.setRenderableType(ctx->api());
    9187        bool ok = false;
     
    117113
    118114    // Retrieve the actual format properties.
    119     qt_egl_update_format(*ctx, format);
     115    qt_glformat_from_eglconfig(format, ctx->config());
    120116
    121117    // Create the attributes needed for the pbuffer.
     
    142138#endif
    143139    if (pbuf == EGL_NO_SURFACE) {
    144         qWarning() << "QGLPixelBufferPrivate::init(): Unable to create EGL pbuffer surface:" << QEglContext::errorString(eglGetError());
     140        qWarning() << "QGLPixelBufferPrivate::init(): Unable to create EGL pbuffer surface:" << QEgl::errorString();
    145141        return false;
    146142    }
     
    209205{
    210206    // See if we have at least 1 configuration that matches the default format.
    211     EGLDisplay dpy = QEglContext::display();
     207    EGLDisplay dpy = QEgl::display();
    212208    if (dpy == EGL_NO_DISPLAY)
    213209        return false;
    214210    QEglProperties configProps;
    215     qt_egl_set_format(configProps, QInternal::Pbuffer, QGLFormat::defaultFormat());
     211    qt_eglproperties_set_glformat(configProps, QGLFormat::defaultFormat());
     212    configProps.setDeviceType(QInternal::Pbuffer);
    216213    configProps.setRenderableType(QEgl::OpenGL);
    217214    do {
  • trunk/src/opengl/qglpixelbuffer_mac.mm

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglpixelbuffer_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6161#include <private/qglpaintdevice_p.h>
    6262
    63 #if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     63#if defined(Q_WS_X11) && defined(QT_NO_EGL)
    6464#include <GL/glx.h>
    6565
     
    128128#elif defined(Q_WS_WIN)
    129129DECLARE_HANDLE(HPBUFFERARB);
    130 #elif defined(QT_OPENGL_ES_2)
    131 #include <EGL/egl.h>
    132 #elif defined(QT_OPENGL_ES)
    133 #include <GLES/egl.h>
     130#elif !defined(QT_NO_EGL)
     131#include <QtGui/private/qegl_p.h>
    134132#endif
    135133QT_END_INCLUDE_NAMESPACE
     
    175173    QSize req_size;
    176174
    177 #if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     175#if defined(Q_WS_X11) && defined(QT_NO_EGL)
    178176    GLXPbuffer pbuf;
    179177    GLXContext ctx;
     
    196194#  endif
    197195#endif
    198 #if defined(QT_OPENGL_ES)
     196#ifndef QT_NO_EGL
    199197    EGLSurface pbuf;
    200198    QEglContext *ctx;
  • trunk/src/opengl/qglpixelbuffer_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    168168#endif
    169169
     170#ifndef WGL_ARB_multisample
     171#define WGL_SAMPLE_BUFFERS_ARB         0x2041
     172#define WGL_SAMPLES_ARB                0x2042
     173#endif
     174
     175#ifndef GL_SAMPLES_ARB
     176#define GL_SAMPLES_ARB 0x80A9
     177#endif
     178
    170179QGLFormat pfiToQGLFormat(HDC hdc, int pfi);
    171180
     
    227236        attribs[i++] = TRUE;
    228237    }
    229     // sample buffers doesn't work in conjunction with the render_texture extension
    230     // so igonre that for now
    231     // if (f.sampleBuffers()) {
    232     //     attribs[i++] = WGL_SAMPLE_BUFFERS_ARB;
    233     //     attribs[i++] = 1;
    234     //     attribs[i++] = WGL_SAMPLES_ARB;
    235     //     attribs[i++] = f.samples() == -1 ? 16 : f.samples();
    236     // }
     238    if (f.sampleBuffers()) {
     239        attribs[i++] = WGL_SAMPLE_BUFFERS_ARB;
     240        attribs[i++] = 1;
     241        attribs[i++] = WGL_SAMPLES_ARB;
     242        attribs[i++] = f.samples() == -1 ? 16 : f.samples();
     243    }
    237244    attribs[i] = 0;
    238245}
     
    240247bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
    241248{
    242     QGLWidget dmy;
    243     dmy.makeCurrent(); // needed for wglGetProcAddress() to succeed
     249    QGLTemporaryContext tempContext;
    244250
    245251    PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB =
     
    255261        return false;
    256262
    257     dc = GetDC(dmy.winId());
     263    dc = wglGetCurrentDC();
    258264    Q_ASSERT(dc);
    259 
    260     PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
    261         (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
    262 
    263     if (wglGetExtensionsStringARB) {
    264         QString extensions(QLatin1String(wglGetExtensionsStringARB(dc)));
    265         has_render_texture = extensions.contains(QLatin1String("WGL_ARB_render_texture"));
     265    has_render_texture = false;
     266
     267    // sample buffers doesn't work in conjunction with the render_texture extension
     268    if (!f.sampleBuffers()) {
     269        PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
     270                (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
     271
     272        if (wglGetExtensionsStringARB) {
     273            QString extensions(QLatin1String(wglGetExtensionsStringARB(dc)));
     274            has_render_texture = extensions.contains(QLatin1String("WGL_ARB_render_texture"));
     275        }
    266276    }
    267277
     
    285295    if (num_formats == 0) {
    286296        qWarning("QGLPixelBuffer: Unable to find a pixel format with pbuffer  - giving up.");
    287         ReleaseDC(dmy.winId(), dc);
    288297        return false;
    289298    }
     
    298307    pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(),
    299308                               has_render_texture ? pb_attribs : 0);
    300     if(!pbuf) {
     309    if (!pbuf) {
    301310        // try again without the render_texture extension
    302311        pbuf = wglCreatePbufferARB(dc, pixel_format, size.width(), size.height(), 0);
     
    304313        if (!pbuf) {
    305314            qWarning("QGLPixelBuffer: Unable to create pbuffer [w=%d, h=%d] - giving up.", size.width(), size.height());
    306             ReleaseDC(dmy.winId(), dc);
    307315            return false;
    308316        }
    309317    }
    310318
    311     ReleaseDC(dmy.winId(), dc);
    312319    dc = wglGetPbufferDCARB(pbuf);
    313320    ctx = wglCreateContext(dc);
    314 
    315321    if (!dc || !ctx) {
    316322        qWarning("QGLPixelBuffer: Unable to create pbuffer context - giving up.");
    317323        return false;
    318324    }
     325
     326    // Explicitly disable the render_texture extension if we have a
     327    // multi-sampled pbuffer context. This seems to be a problem only with
     328    // ATI cards if multi-sampling is forced globally in the driver.
     329    wglMakeCurrent(dc, ctx);
     330    GLint samples = 0;
     331    glGetIntegerv(GL_SAMPLES_ARB, &samples);
     332    if (has_render_texture && samples != 0)
     333        has_render_texture = false;
    319334
    320335    HGLRC share_ctx = shareWidget ? shareWidget->d_func()->glcx->d_func()->rc : 0;
  • trunk/src/opengl/qglpixelbuffer_x11.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglpixmapfilter.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6464
    6565// qpixmapfilter.cpp
    66 void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
    67 QImage qt_halfScaled(const QImage &source);
     66Q_DECL_IMPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
     67Q_DECL_IMPORT QImage qt_halfScaled(const QImage &source);
    6868
    6969void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const
     
    437437}
    438438
    439 void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride,
     439Q_DECL_IMPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride,
    440440                       quint32 *dest, int dstStride);
    441441
  • trunk/src/opengl/qglpixmapfilter_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglscreen_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglscreen_qws.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglshaderprogram.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151QT_BEGIN_NAMESPACE
    5252
    53 #if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
     53#if !defined(QT_OPENGL_ES_1)
    5454
    5555/*!
     
    144144    \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
    145145    \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
     146    \value Geometry Geometry shaders written in the OpenGL Shading
     147           Language (GLSL), based on the GL_EXT_geometry_shader4 extension.
    146148*/
    147149
     
    227229        if (shaderType == QGLShader::Vertex)
    228230            shader = glCreateShader(GL_VERTEX_SHADER);
     231        else if (shaderType == QGLShader::Geometry)
     232            shader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
    229233        else
    230234            shader = glCreateShader(GL_FRAGMENT_SHADER);
     
    510514}
    511515
     516
     517
     518
     519
    512520#undef ctx
    513521#define ctx programGuard.context()
     
    522530        , inited(false)
    523531        , removingShaders(false)
    524         , vertexShader(0)
    525         , fragmentShader(0)
     532        , geometryVertexCount(64)
     533        , geometryInputType(0)
     534        , geometryOutputType(0)
    526535    {
    527536    }
     
    532541    bool inited;
    533542    bool removingShaders;
     543
     544    int geometryVertexCount;
     545    GLenum geometryInputType;
     546    GLenum geometryOutputType;
     547
    534548    QString log;
    535549    QList<QGLShader *> shaders;
    536550    QList<QGLShader *> anonShaders;
    537     QGLShader *vertexShader;
    538     QGLShader *fragmentShader;
    539551
    540552    bool hasShader(QGLShader::ShaderType type) const;
     
    605617        d->programGuard.setContext(context);
    606618    }
     619
    607620    if (!context)
    608621        return false;
     
    832845    if (!program)
    833846        return false;
     847
    834848    GLint value;
    835849    if (d->shaders.isEmpty()) {
     
    844858            return true;
    845859    }
     860
     861    // Set up the geometry shader parameters
     862    if (glProgramParameteriEXT) {
     863        foreach (QGLShader *shader, d->shaders) {
     864            if (shader->shaderType() & QGLShader::Geometry) {
     865                glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT,
     866                                       d->geometryInputType);
     867                glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
     868                                       d->geometryOutputType);
     869                glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT,
     870                                       d->geometryVertexCount);
     871                break;
     872            }
     873        }
     874    }
     875
    846876    glLinkProgram(program);
    847877    value = 0;
     
    12681298    Q_UNUSED(d);
    12691299    if (location != -1) {
    1270         GLfloat values[4] = {value.redF(), value.greenF(), value.blueF(), value.alphaF()};
     1300        GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()),
     1301                             GLfloat(value.blueF()), GLfloat(value.alphaF())};
    12711302        glVertexAttrib4fv(location, values);
    12721303    }
     
    14341465
    14351466/*!
     1467    Sets an array of vertex \a values on the attribute at \a location
     1468    in this shader program.  The \a stride indicates the number of bytes
     1469    between vertices.  A default \a stride value of zero indicates that
     1470    the vertices are densely packed in \a values.
     1471
     1472    The \a type indicates the type of elements in the \a values array,
     1473    usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a tupleSize
     1474    indicates the number of components per vertex: 1, 2, 3, or 4.
     1475
     1476    The array will become active when enableAttributeArray() is called
     1477    on the \a location.  Otherwise the value specified with
     1478    setAttributeValue() for \a location will be used.
     1479
     1480    The setAttributeBuffer() function can be used to set the attribute
     1481    array to an offset within a vertex buffer.
     1482
     1483    \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
     1484    \sa disableAttributeArray(), setAttributeBuffer()
     1485    \since 4.7
     1486*/
     1487void QGLShaderProgram::setAttributeArray
     1488    (int location, GLenum type, const void *values, int tupleSize, int stride)
     1489{
     1490    Q_D(QGLShaderProgram);
     1491    Q_UNUSED(d);
     1492    if (location != -1) {
     1493        glVertexAttribPointer(location, tupleSize, type, GL_TRUE,
     1494                              stride, values);
     1495    }
     1496}
     1497
     1498/*!
    14361499    \overload
    14371500
     
    15161579{
    15171580    setAttributeArray(attributeLocation(name), values, stride);
     1581}
     1582
     1583/*!
     1584    \overload
     1585
     1586    Sets an array of vertex \a values on the attribute called \a name
     1587    in this shader program.  The \a stride indicates the number of bytes
     1588    between vertices.  A default \a stride value of zero indicates that
     1589    the vertices are densely packed in \a values.
     1590
     1591    The \a type indicates the type of elements in the \a values array,
     1592    usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a tupleSize
     1593    indicates the number of components per vertex: 1, 2, 3, or 4.
     1594
     1595    The array will become active when enableAttributeArray() is called
     1596    on the \a name.  Otherwise the value specified with
     1597    setAttributeValue() for \a name will be used.
     1598
     1599    The setAttributeBuffer() function can be used to set the attribute
     1600    array to an offset within a vertex buffer.
     1601
     1602    \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
     1603    \sa disableAttributeArray(), setAttributeBuffer()
     1604    \since 4.7
     1605*/
     1606void QGLShaderProgram::setAttributeArray
     1607    (const char *name, GLenum type, const void *values, int tupleSize, int stride)
     1608{
     1609    setAttributeArray(attributeLocation(name), type, values, tupleSize, stride);
     1610}
     1611
     1612/*!
     1613    Sets an array of vertex values on the attribute at \a location in
     1614    this shader program, starting at a specific \a offset in the
     1615    currently bound vertex buffer.  The \a stride indicates the number
     1616    of bytes between vertices.  A default \a stride value of zero
     1617    indicates that the vertices are densely packed in the value array.
     1618
     1619    The \a type indicates the type of elements in the vertex value
     1620    array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a
     1621    tupleSize indicates the number of components per vertex: 1, 2, 3,
     1622    or 4.
     1623
     1624    The array will become active when enableAttributeArray() is called
     1625    on the \a location.  Otherwise the value specified with
     1626    setAttributeValue() for \a location will be used.
     1627
     1628    \sa setAttributeArray()
     1629    \since 4.7
     1630*/
     1631void QGLShaderProgram::setAttributeBuffer
     1632    (int location, GLenum type, int offset, int tupleSize, int stride)
     1633{
     1634    Q_D(QGLShaderProgram);
     1635    Q_UNUSED(d);
     1636    if (location != -1) {
     1637        glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride,
     1638                              reinterpret_cast<const void *>(offset));
     1639    }
     1640}
     1641
     1642/*!
     1643    \overload
     1644
     1645    Sets an array of vertex values on the attribute called \a name
     1646    in this shader program, starting at a specific \a offset in the
     1647    currently bound vertex buffer.  The \a stride indicates the number
     1648    of bytes between vertices.  A default \a stride value of zero
     1649    indicates that the vertices are densely packed in the value array.
     1650
     1651    The \a type indicates the type of elements in the vertex value
     1652    array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc.  The \a
     1653    tupleSize indicates the number of components per vertex: 1, 2, 3,
     1654    or 4.
     1655
     1656    The array will become active when enableAttributeArray() is called
     1657    on the \a name.  Otherwise the value specified with
     1658    setAttributeValue() for \a name will be used.
     1659
     1660    \sa setAttributeArray()
     1661    \since 4.7
     1662*/
     1663void QGLShaderProgram::setAttributeBuffer
     1664    (const char *name, GLenum type, int offset, int tupleSize, int stride)
     1665{
     1666    setAttributeBuffer(attributeLocation(name), type, offset, tupleSize, stride);
    15181667}
    15191668
     
    18852034    Q_UNUSED(d);
    18862035    if (location != -1) {
    1887         GLfloat values[4] = {color.redF(), color.greenF(), color.blueF(), color.alphaF()};
     2036        GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()),
     2037                             GLfloat(color.blueF()), GLfloat(color.alphaF())};
    18882038        glUniform4fv(location, 1, values);
    18892039    }
     
    19142064    Q_UNUSED(d);
    19152065    if (location != -1) {
    1916         GLfloat values[4] = {point.x(), point.y()};
     2066        GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
    19172067        glUniform2fv(location, 1, values);
    19182068    }
     
    19432093    Q_UNUSED(d);
    19442094    if (location != -1) {
    1945         GLfloat values[4] = {point.x(), point.y()};
     2095        GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
    19462096        glUniform2fv(location, 1, values);
    19472097    }
     
    19722122    Q_UNUSED(d);
    19732123    if (location != -1) {
    1974         GLfloat values[4] = {size.width(), size.width()};
     2124        GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
    19752125        glUniform2fv(location, 1, values);
    19762126    }
     
    20012151    Q_UNUSED(d);
    20022152    if (location != -1) {
    2003         GLfloat values[4] = {size.width(), size.height()};
     2153        GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
    20042154        glUniform2fv(location, 1, values);
    20052155    }
     
    23152465
    23162466    Sets the uniform variable at \a location in the current context
     2467    to a 2x2 matrix \a value.  The matrix elements must be specified
     2468    in column-major order.
     2469
     2470    \sa setAttributeValue()
     2471    \since 4.7
     2472*/
     2473void QGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2])
     2474{
     2475    Q_D(QGLShaderProgram);
     2476    Q_UNUSED(d);
     2477    if (location != -1)
     2478        glUniformMatrix2fv(location, 1, GL_FALSE, value[0]);
     2479}
     2480
     2481/*!
     2482    \overload
     2483
     2484    Sets the uniform variable at \a location in the current context
     2485    to a 3x3 matrix \a value.  The matrix elements must be specified
     2486    in column-major order.
     2487
     2488    \sa setAttributeValue()
     2489    \since 4.7
     2490*/
     2491void QGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3])
     2492{
     2493    Q_D(QGLShaderProgram);
     2494    Q_UNUSED(d);
     2495    if (location != -1)
     2496        glUniformMatrix3fv(location, 1, GL_FALSE, value[0]);
     2497}
     2498
     2499/*!
     2500    \overload
     2501
     2502    Sets the uniform variable at \a location in the current context
    23172503    to a 4x4 matrix \a value.  The matrix elements must be specified
    23182504    in column-major order.
     
    23262512    if (location != -1)
    23272513        glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
     2514}
     2515
     2516
     2517/*!
     2518    \overload
     2519
     2520    Sets the uniform variable called \a name in the current context
     2521    to a 2x2 matrix \a value.  The matrix elements must be specified
     2522    in column-major order.
     2523
     2524    \sa setAttributeValue()
     2525    \since 4.7
     2526*/
     2527void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2])
     2528{
     2529    setUniformValue(uniformLocation(name), value);
     2530}
     2531
     2532/*!
     2533    \overload
     2534
     2535    Sets the uniform variable called \a name in the current context
     2536    to a 3x3 matrix \a value.  The matrix elements must be specified
     2537    in column-major order.
     2538
     2539    \sa setAttributeValue()
     2540    \since 4.7
     2541*/
     2542void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3])
     2543{
     2544    setUniformValue(uniformLocation(name), value);
    23282545}
    23292546
     
    23552572    if (location != -1) {
    23562573        GLfloat mat[3][3] = {
    2357             {value.m11(), value.m12(), value.m13()},
    2358             {value.m21(), value.m22(), value.m23()},
    2359             {value.m31(), value.m32(), value.m33()}
     2574            {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())},
     2575            {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())},
     2576            {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())}
    23602577        };
    23612578        glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
     
    28703087
    28713088/*!
     3089    Returns the hardware limit for how many vertices a geometry shader
     3090    can output.
     3091
     3092    \since 4.7
     3093
     3094    \sa setGeometryOutputVertexCount()
     3095*/
     3096int QGLShaderProgram::maxGeometryOutputVertices() const
     3097{
     3098    GLint n;
     3099    glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
     3100    return n;
     3101}
     3102
     3103/*!
     3104    Sets the maximum number of vertices the current geometry shader
     3105    program will produce, if active, to \a count.
     3106
     3107    \since 4.7
     3108
     3109    This parameter takes effect the next time the program is linked.
     3110*/
     3111void QGLShaderProgram::setGeometryOutputVertexCount(int count)
     3112{
     3113#ifndef QT_NO_DEBUG
     3114    int max = maxGeometryOutputVertices();
     3115    if (count > max) {
     3116        qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
     3117                 count, max);
     3118    }
     3119#endif
     3120    d_func()->geometryVertexCount = count;
     3121}
     3122
     3123
     3124/*!
     3125    Returns the maximum number of vertices the current geometry shader
     3126    program will produce, if active.
     3127
     3128    \since 4.7
     3129
     3130    This parameter takes effect the ntext time the program is linked.
     3131*/
     3132int QGLShaderProgram::geometryOutputVertexCount() const
     3133{
     3134    return d_func()->geometryVertexCount;
     3135}
     3136
     3137
     3138/*!
     3139    Sets the input type from \a inputType.
     3140
     3141    This parameter takes effect the next time the program is linked.
     3142*/
     3143void QGLShaderProgram::setGeometryInputType(GLenum inputType)
     3144{
     3145    d_func()->geometryInputType = inputType;
     3146}
     3147
     3148
     3149/*!
     3150    Returns the geometry shader input type, if active.
     3151
     3152    This parameter takes effect the next time the program is linked.
     3153
     3154    \since 4.7
     3155 */
     3156
     3157GLenum QGLShaderProgram::geometryInputType() const
     3158{
     3159    return d_func()->geometryInputType;
     3160}
     3161
     3162
     3163/*!
     3164    Sets the output type from the geometry shader, if active, to
     3165    \a outputType.
     3166
     3167    This parameter takes effect the next time the program is linked.
     3168
     3169    \since 4.7
     3170*/
     3171void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
     3172{
     3173    d_func()->geometryOutputType = outputType;
     3174}
     3175
     3176
     3177/*!
     3178    Returns the geometry shader output type, if active.
     3179
     3180    This parameter takes effect the next time the program is linked.
     3181
     3182    \since 4.7
     3183 */
     3184GLenum QGLShaderProgram::geometryOutputType() const
     3185{
     3186    return d_func()->geometryOutputType;
     3187}
     3188
     3189
     3190/*!
    28723191    Returns true if shader programs written in the OpenGL Shading
    28733192    Language (GLSL) are supported on this system; false otherwise.
     
    29013220}
    29023221
     3222
     3223#undef ctx
     3224#undef context
     3225
     3226/*!
     3227    Returns true if shader programs of type \a type are supported on
     3228    this system; false otherwise.
     3229
     3230    The \a context is used to resolve the GLSL extensions.
     3231    If \a context is null, then QGLContext::currentContext() is used.
     3232
     3233    \since 4.7
     3234*/
     3235bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
     3236{
     3237    if (!context)
     3238        context = QGLContext::currentContext();
     3239    if (!context)
     3240        return false;
     3241
     3242    if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
     3243        return false;
     3244
     3245    bool resolved = qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
     3246    if (!resolved)
     3247        return false;
     3248
     3249    if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
     3250        return false;
     3251
     3252    return true;
     3253}
     3254
     3255
     3256
    29033257#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
    29043258/*! \internal */
     3259void QGLShaderProgram::setAttributeArray
     3260    (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride)
     3261{
     3262    setAttributeArray(location, GLenum(type), values, tupleSize, stride);
     3263}
     3264
     3265/*! \internal */
     3266void QGLShaderProgram::setAttributeArray
     3267    (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride)
     3268{
     3269    setAttributeArray(name, GLenum(type), values, tupleSize, stride);
     3270}
     3271
     3272/*! \internal */
     3273void QGLShaderProgram::setAttributeBuffer
     3274    (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride)
     3275{
     3276    setAttributeBuffer(location, GLenum(type), offset, tupleSize, stride);
     3277}
     3278
     3279/*! \internal */
     3280void QGLShaderProgram::setAttributeBuffer
     3281    (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride)
     3282{
     3283    setAttributeBuffer(name, GLenum(type), offset, tupleSize, stride);
     3284}
     3285
     3286/*! \internal */
    29053287void QGLShaderProgram::setUniformValue(int location, QMacCompatGLint value)
    29063288{
     
    29513333#endif
    29523334
    2953 #endif // !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
     3335#endif // !defined(QT_OPENGL_ES_1)
    29543336
    29553337QT_END_NAMESPACE
  • trunk/src/opengl/qglshaderprogram.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555QT_MODULE(OpenGL)
    5656
    57 #if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
     57#if !defined(QT_OPENGL_ES_1)
    5858
    5959class QGLShaderProgram;
     
    6767    {
    6868        Vertex          = 0x0001,
    69         Fragment        = 0x0002
     69        Fragment        = 0x0002,
     70        Geometry        = 0x0004
    7071    };
    7172    Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
     
    8990    GLuint shaderId() const;
    9091
     92    static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = 0);
     93
    9194private:
    9295    friend class QGLShaderProgram;
     
    100103
    101104class QGLShaderProgramPrivate;
     105
     106#ifndef GL_EXT_geometry_shader4
     107#  define GL_LINES_ADJACENCY_EXT 0xA
     108#  define GL_LINE_STRIP_ADJACENCY_EXT 0xB
     109#  define GL_TRIANGLES_ADJACENCY_EXT 0xC
     110#  define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
     111#endif
     112
    102113
    103114class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
     
    128139
    129140    GLuint programId() const;
     141
     142    int maxGeometryOutputVertices() const;
     143
     144    void setGeometryOutputVertexCount(int count);
     145    int geometryOutputVertexCount() const;
     146
     147    void setGeometryInputType(GLenum inputType);
     148    GLenum geometryInputType() const;
     149
     150    void setGeometryOutputType(GLenum outputType);
     151    GLenum geometryOutputType() const;
    130152
    131153    void bindAttributeLocation(const char *name, int location);
     
    166188        (int location, const QVector4D *values, int stride = 0);
    167189    void setAttributeArray
     190        (int location, GLenum type, const void *values, int tupleSize, int stride = 0);
     191    void setAttributeArray
    168192        (const char *name, const GLfloat *values, int tupleSize, int stride = 0);
    169193    void setAttributeArray
     
    173197    void setAttributeArray
    174198        (const char *name, const QVector4D *values, int stride = 0);
     199    void setAttributeArray
     200        (const char *name, GLenum type, const void *values, int tupleSize, int stride = 0);
     201
     202    void setAttributeBuffer
     203        (int location, GLenum type, int offset, int tupleSize, int stride = 0);
     204    void setAttributeBuffer
     205        (const char *name, GLenum type, int offset, int tupleSize, int stride = 0);
     206
     207#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
     208    void setAttributeArray
     209        (int location, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0);
     210    void setAttributeArray
     211        (const char *name, QMacCompatGLenum type, const void *values, int tupleSize, int stride = 0);
     212    void setAttributeBuffer
     213        (int location, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0);
     214    void setAttributeBuffer
     215        (const char *name, QMacCompatGLenum type, int offset, int tupleSize, int stride = 0);
     216#endif
    175217
    176218    void enableAttributeArray(int location);
     
    217259    void setUniformValue(int location, const QMatrix4x3& value);
    218260    void setUniformValue(int location, const QMatrix4x4& value);
     261    void setUniformValue(int location, const GLfloat value[2][2]);
     262    void setUniformValue(int location, const GLfloat value[3][3]);
    219263    void setUniformValue(int location, const GLfloat value[4][4]);
    220264    void setUniformValue(int location, const QTransform& value);
     
    243287    void setUniformValue(const char *name, const QMatrix4x3& value);
    244288    void setUniformValue(const char *name, const QMatrix4x4& value);
     289    void setUniformValue(const char *name, const GLfloat value[2][2]);
     290    void setUniformValue(const char *name, const GLfloat value[3][3]);
    245291    void setUniformValue(const char *name, const GLfloat value[4][4]);
    246292    void setUniformValue(const char *name, const QTransform& value);
  • trunk/src/opengl/qglwindowsurface_qws.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qglwindowsurface_qws_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qgraphicsshadereffect.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include "qgraphicsshadereffect_p.h"
    43 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     43#if !defined(QT_OPENGL_ES_1)
    4444#include "qglshaderprogram.h"
    4545#include "gl2paintengineex/qglcustomshaderstage_p.h"
  • trunk/src/opengl/qgraphicsshadereffect_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/qgraphicssystem_gl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include "qgraphicssystem_gl_p.h"
     43#include <QGraphicsView>
    4344
    4445#include "private/qpixmap_raster_p.h"
     
    4849#include <private/qwindowsurface_raster_p.h>
    4950
    50 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     51#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
    5152#include "private/qpixmapdata_x11gl_p.h"
    5253#include "private/qwindowsurface_x11gl_p.h"
     
    5960QPixmapData *QGLGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
    6061{
    61 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
    62     if (type == QPixmapData::PixmapType && QX11GLPixmapData::hasX11GLPixmaps())
    63         return new QX11GLPixmapData();
    64 #endif
    65 
    6662    return new QGLPixmapData(type);
    6763}
     
    7773#endif
    7874
    79 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
    80     if (QX11GLPixmapData::hasX11GLPixmaps())
    81         return new QX11GLWindowSurface(widget);
     75#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
     76    if (m_useX11GL && QX11GLPixmapData::hasX11GLPixmaps()) {
     77        // If the widget is a QGraphicsView which will be re-drawing the entire
     78        // scene each frame anyway, we should use QGLWindowSurface as this may
     79        // provide proper buffer flipping, which should be faster than QX11GL's
     80        // blitting approach:
     81        QGraphicsView* qgv = qobject_cast<QGraphicsView*>(widget);
     82        if (qgv && qgv->viewportUpdateMode() == QGraphicsView::FullViewportUpdate)
     83            return new QGLWindowSurface(widget);
     84        else
     85            return new QX11GLWindowSurface(widget);
     86    }
    8287#endif
    8388
  • trunk/src/opengl/qgraphicssystem_gl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363{
    6464public:
    65     QGLGraphicsSystem();
     65    QGLGraphicsSystem(bool useX11GL);
    6666
    6767    QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
    6868    QWindowSurface *createWindowSurface(QWidget *widget) const;
     69private:
     70    bool m_useX11GL;
    6971};
    7072
  • trunk/src/opengl/qpaintengine_opengl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6161#include <private/qbezier_p.h>
    6262#include <qglframebufferobject.h>
     63#include <private/qstatictext_p.h>
    6364
    6465#include "private/qtessellator_p.h"
     
    7273#endif
    7374
    74 #ifdef QT_OPENGL_ES_1_CL
    75 #include "qgl_cl_p.h"
    76 #endif
    77 
    7875#define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context());
    7976
     
    8380QT_BEGIN_NAMESPACE
    8481
    85 extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
     82Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
    8683#ifdef QT_MAC_USE_COCOA
    8784extern void *qt_current_nsopengl_context(); // qgl_mac.mm
     
    510507////////// GL program cache: start
    511508
    512 typedef struct {
     509struct GLProgram {
    513510    int brush; // brush index or mask index
    514511    int mode;  // composition mode index
    515512    bool mask;
    516513    GLuint program;
    517 } GLProgram;
     514};
    518515
    519516typedef QMultiHash<const QGLContext *, GLProgram> QGLProgramHash;
     
    672669        , shader_ctx(0)
    673670        , grad_palette(0)
     671        , tess_points(0)
    674672        , drawable_texture(0)
    675673        , ref_cleaner(this)
     
    781779
    782780    void composite(const QRectF &rect, const QPoint &maskOffset = QPoint());
    783     void composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint());
     781    void composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint());
    784782
    785783    bool createFragmentPrograms();
     
    924922    stroker.setJoinStyle(cpen.joinStyle());
    925923    stroker.setMiterLimit(cpen.miterLimit());
     924    stroker.setDashOffset(cpen.dashOffset());
    926925
    927926    qreal width = cpen.widthF();
     
    17931792    QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {}
    17941793    ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); }
    1795     q_vertexType *vertices;
     1794    GLfloat *vertices;
    17961795    int allocated;
    17971796    int size;
     
    18141813#endif
    18151814        allocated = qMax(2*allocated, 512);
    1816         vertices = (q_vertexType *)realloc(vertices, allocated * sizeof(q_vertexType));
     1815        vertices = (GLfloat *)realloc(vertices, allocated * sizeof(GLfloat));
    18171816    }
    18181817
     
    18201819
    18211820#ifndef QT_OPENGL_ES
    1822     vertices[size++] = f2vt(t.topLeftX);
    1823     vertices[size++] = f2vt(t.top);
    1824     vertices[size++] = f2vt(t.topRightX);
    1825     vertices[size++] = f2vt(t.top);
    1826     vertices[size++] = f2vt(t.bottomRightX);
    1827     vertices[size++] = f2vt(t.bottom);
    1828     vertices[size++] = f2vt(t.bottomLeftX);
    1829     vertices[size++] = f2vt(t.bottom);
     1821    vertices[size++] = t.topLeftX;
     1822    vertices[size++] = t.top;
     1823    vertices[size++] = t.topRightX;
     1824    vertices[size++] = t.top;
     1825    vertices[size++] = t.bottomRightX;
     1826    vertices[size++] = t.bottom;
     1827    vertices[size++] = t.bottomLeftX;
     1828    vertices[size++] = t.bottom;
    18301829#else
    18311830    // First triangle
    1832     vertices[size++] = f2vt(t.topLeftX);
    1833     vertices[size++] = f2vt(t.top);
    1834     vertices[size++] = f2vt(t.topRightX);
    1835     vertices[size++] = f2vt(t.top);
    1836     vertices[size++] = f2vt(t.bottomRightX);
    1837     vertices[size++] = f2vt(t.bottom);
     1831    vertices[size++] = t.topLeftX;
     1832    vertices[size++] = t.top;
     1833    vertices[size++] = t.topRightX;
     1834    vertices[size++] = t.top;
     1835    vertices[size++] = t.bottomRightX;
     1836    vertices[size++] = t.bottom;
    18381837
    18391838    // Second triangle
    1840     vertices[size++] = f2vt(t.bottomLeftX);
    1841     vertices[size++] = f2vt(t.bottom);
    1842     vertices[size++] = f2vt(t.topLeftX);
    1843     vertices[size++] = f2vt(t.top);
    1844     vertices[size++] = f2vt(t.bottomRightX);
    1845     vertices[size++] = f2vt(t.bottom);
     1839    vertices[size++] = t.bottomLeftX;
     1840    vertices[size++] = t.bottom;
     1841    vertices[size++] = t.topLeftX;
     1842    vertices[size++] = t.top;
     1843    vertices[size++] = t.bottomRightX;
     1844    vertices[size++] = t.bottom;
    18461845#endif
    18471846}
     
    18701869        composite(geometry_mode, tessellator.vertices, tessellator.size / 2);
    18711870    } else {
    1872         glVertexPointer(2, q_vertexTypeEnum, 0, tessellator.vertices);
     1871        glVertexPointer(2, GL_FLOAT, 0, tessellator.vertices);
    18731872        glEnableClientState(GL_VERTEX_ARRAY);
    18741873        glDrawArrays(geometry_mode, 0, tessellator.size/2);
     
    19591958void QOpenGLPaintEnginePrivate::drawVertexArrays()
    19601959{
     1960    if (tess_points_stops.count() == 0)
     1961        return;
    19611962    glEnableClientState(GL_VERTEX_ARRAY);
    19621963    glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
     
    22712272    }
    22722273
    2273 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_1_CL)
     2274#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2)
    22742275    glClearDepthf(0.0f);
    22752276#else
     
    22872288
    22882289    // rectangle count * 2 (triangles) * vertex count * component count (Z omitted)
    2289     QDataBuffer<q_vertexType> clipVertex(rects.size()*2*3*2);
     2290    QDataBuffer<GLfloat> clipVertex(rects.size()*2*3*2);
    22902291    for (int i = 0; i < rects.size(); ++i) {
    2291         q_vertexType x = i2vt(rects.at(i).left());
    2292         q_vertexType w = i2vt(rects.at(i).width());
    2293         q_vertexType h = i2vt(rects.at(i).height());
    2294         q_vertexType y = i2vt(rects.at(i).top());
     2292        GLfloat x = GLfloat(rects.at(i).left());
     2293        GLfloat w = GLfloat(rects.at(i).width());
     2294        GLfloat h = GLfloat(rects.at(i).height());
     2295        GLfloat y = GLfloat(rects.at(i).top());
    22952296
    22962297        // First triangle
     
    23202321
    23212322        glEnableClientState(GL_VERTEX_ARRAY);
    2322         glVertexPointer(2, q_vertexTypeEnum, 0, clipVertex.data());
     2323        glVertexPointer(2, GL_FLOAT, 0, clipVertex.data());
    23232324
    23242325        glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3);
     
    31123113}
    31133114
    3114 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
    3115 extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
     3115extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array);
     3116extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array);
    31163117
    31173118void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
     
    31443145    // clear mask
    31453146    glBlendFunc(GL_ZERO, GL_ZERO); // clear
    3146     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3147    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    31473148    glEnableClientState(GL_VERTEX_ARRAY);
    31483149    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     
    33513352    QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate;
    33523353
    3353     float m[3][4] = { { inv_matrix.m11(), inv_matrix.m12(), inv_matrix.m13() },
    3354                       { inv_matrix.m21(), inv_matrix.m22(), inv_matrix.m23() },
    3355                       { inv_matrix.m31(), inv_matrix.m32(), inv_matrix.m33() } };
     3354    float m[3][4] = { { float(inv_matrix.m11()), float(inv_matrix.m12()), float(inv_matrix.m13()) },
     3355                      { float(inv_matrix.m21()), float(inv_matrix.m22()), float(inv_matrix.m23()) },
     3356                      { float(inv_matrix.m31()), float(inv_matrix.m32()), float(inv_matrix.m33()) } };
    33563357
    33573358    QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top())
     
    33593360
    33603361    // last component needs to be 1.0f to avoid Nvidia bug on linux
    3361     float ellipse_offset[4] = { offs.x(), offs.y(), 0.0f, 1.0f };
     3362    float ellipse_offset[4] = { float(offs.x()), float(offs.y()), 0.0f, 1.0f };
    33623363
    33633364    GLfloat vertexArray[4 * 2];
     
    33753376
    33763377    glEnableClientState(GL_VERTEX_ARRAY);
    3377     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3378    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    33783379    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    33793380    glDisableClientState(GL_VERTEX_ARRAY);
     
    34053406    DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect");
    34063407
    3407     q_vertexType vertexArray[10];
     3408    GLfloat vertexArray[10];
    34083409    qt_add_rect_to_array(r, vertexArray);
    34093410
     
    34263427        if (fast_style && has_fast_composition_mode) {
    34273428            glEnableClientState(GL_VERTEX_ARRAY);
    3428             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3429            glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    34293430            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    34303431            glDisableClientState(GL_VERTEX_ARRAY);
     
    34453446            vertexArray[9] = vertexArray[1];
    34463447
    3447             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3448            glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    34483449            glEnableClientState(GL_VERTEX_ARRAY);
    34493450            glDrawArrays(GL_LINE_STRIP, 0, 5);
     
    35523553}
    35533554
    3554 static void addQuadAsTriangle(q_vertexType *quad, q_vertexType *triangle)
     3555static void addQuadAsTriangle(GLfloat *quad, GLfloat *triangle)
    35553556{
    35563557    triangle[0] = quad[0];
     
    36133614
    36143615    if (d->has_fast_pen) {
    3615         QVarLengthArray<q_vertexType> vertexArray(6 * pointCount);
     3616        QVarLengthArray<GLfloat> vertexArray(6 * pointCount);
    36163617
    36173618        glMatrixMode(GL_MODELVIEW);
     
    36233624            QPointF mapped = d->matrix.map(points[i]);
    36243625
    3625             qreal xf = qRound(mapped.x());
    3626             qreal yf = qRound(mapped.y());
    3627 
    3628             q_vertexType x = f2vt(xf);
    3629             q_vertexType y = f2vt(yf);
     3626            GLfloat x = GLfloat(qRound(mapped.x()));
     3627            GLfloat y = GLfloat(qRound(mapped.y()));
    36303628
    36313629            vertexArray[j++] = x;
    3632             vertexArray[j++] = y - f2vt(0.5);
    3633 
    3634             vertexArray[j++] = x + f2vt(1.5);
    3635             vertexArray[j++] = y + f2vt(1.0);
     3630            vertexArray[j++] = y - 0.5f;
     3631
     3632            vertexArray[j++] = x + 1.5f;
     3633            vertexArray[j++] = y + 1.0f;
    36363634
    36373635            vertexArray[j++] = x;
    3638             vertexArray[j++] = y + f2vt(1.0);
     3636            vertexArray[j++] = y + 1.0f;
    36393637        }
    36403638
    36413639        glEnableClientState(GL_VERTEX_ARRAY);
    36423640
    3643         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
     3641        glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
    36443642        glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
    36453643
     
    36583656    else {
    36593657        Q_ASSERT(sizeof(QPointF) == 8);
    3660         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3658        glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    36613659    }
    36623660
     
    37263724            }
    37273725
    3728             q_vertexType endCap = f2vt(d->cpen.capStyle() == Qt::FlatCap ? 0 : 0.5);
     3726            GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f;
    37293727            if (useRects) {
    3730                 QVarLengthArray<q_vertexType> vertexArray(12 * lineCount);
    3731 
    3732                 q_vertexType quad[8];
     3728                QVarLengthArray<GLfloat> vertexArray(12 * lineCount);
     3729
     3730                GLfloat quad[8];
    37333731                for (int i = 0; i < lineCount; ++i) {
    3734                     q_vertexType x1 = f2vt(lines[i].x1());
    3735                     q_vertexType x2 = f2vt(lines[i].x2());
    3736                     q_vertexType y1 = f2vt(lines[i].y1());
    3737                     q_vertexType y2 = f2vt(lines[i].y2());
     3732                    GLfloat x1 = lines[i].x1();
     3733                    GLfloat x2 = lines[i].x2();
     3734                    GLfloat y1 = lines[i].y1();
     3735                    GLfloat y2 = lines[i].y2();
    37383736
    37393737                    if (x1 == x2) {
     
    37413739                            qSwap(y1, y2);
    37423740
    3743                         quad[0] = x1 - f2vt(0.5);
     3741                        quad[0] = x1 - 0.5f;
    37443742                        quad[1] = y1 - endCap;
    37453743
    3746                         quad[2] = x1 + f2vt(0.5);
     3744                        quad[2] = x1 + 0.5f;
    37473745                        quad[3] = y1 - endCap;
    37483746
    3749                         quad[4] = x1 + f2vt(0.5);
     3747                        quad[4] = x1 + 0.5f;
    37503748                        quad[5] = y2 + endCap;
    37513749
    3752                         quad[6] = x1 - f2vt(0.5);
     3750                        quad[6] = x1 - 0.5f;
    37533751                        quad[7] = y2 + endCap;
    37543752                    } else {
     
    37573755
    37583756                        quad[0] = x1 - endCap;
    3759                         quad[1] = y1 + f2vt(0.5);
     3757                        quad[1] = y1 + 0.5f;
    37603758
    37613759                        quad[2] = x1 - endCap;
    3762                         quad[3] = y1 - f2vt(0.5);
     3760                        quad[3] = y1 - 0.5f;
    37633761
    37643762                        quad[4] = x2 + endCap;
    3765                         quad[5] = y1 - f2vt(0.5);
     3763                        quad[5] = y1 - 0.5f;
    37663764
    37673765                        quad[6] = x2 + endCap;
    3768                         quad[7] = y1 + f2vt(0.5);
     3766                        quad[7] = y1 + 0.5f;
    37693767                    }
    37703768
     
    37743772                glEnableClientState(GL_VERTEX_ARRAY);
    37753773
    3776                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
     3774                glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
    37773775                glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
    37783776
    37793777                glDisableClientState(GL_VERTEX_ARRAY);
    37803778            } else {
    3781                 QVarLengthArray<q_vertexType> vertexArray(4 * lineCount);
     3779                QVarLengthArray<GLfloat> vertexArray(4 * lineCount);
    37823780                for (int i = 0; i < lineCount; ++i) {
    37833781                    const QPointF a = lines[i].p1();
    3784                     vertexArray[4*i]   = f2vt(lines[i].x1());
    3785                     vertexArray[4*i+1] = f2vt(lines[i].y1());
    3786                     vertexArray[4*i+2] = f2vt(lines[i].x2());
    3787                     vertexArray[4*i+3] = f2vt(lines[i].y2());
     3782                    vertexArray[4*i]   = lines[i].x1();
     3783                    vertexArray[4*i+1] = lines[i].y1();
     3784                    vertexArray[4*i+2] = lines[i].x2();
     3785                    vertexArray[4*i+3] = lines[i].y2();
    37883786                }
    37893787
    37903788                glEnableClientState(GL_VERTEX_ARRAY);
    37913789
    3792                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
     3790                glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
    37933791                glDrawArrays(GL_LINES, 0, lineCount*2);
    37943792
    3795                 glVertexPointer(2, q_vertexTypeEnum, 4*sizeof(q_vertexType), vertexArray.constData() + 2);
     3793                glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2);
    37963794                glDrawArrays(GL_POINTS, 0, lineCount);
    37973795
     
    38803878            else {
    38813879                Q_ASSERT(sizeof(QPointF) == 8);
    3882                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     3880                glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    38833881            }
    38843882
     
    38993897        if (d->has_fast_pen && !d->high_quality_antialiasing) {
    39003898            d->setGradientOps(d->cpen.brush(), bounds);
    3901             QVarLengthArray<q_vertexType> vertexArray(pointCount*2 + 2);
    3902             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
     3899            QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2);
     3900            glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
    39033901            int i;
    39043902            for (i=0; i<pointCount; ++i) {
    3905                 vertexArray[i*2] = f2vt(points[i].x());
    3906                 vertexArray[i*2+1] = f2vt(points[i].y());
     3903                vertexArray[i*2] = points[i].x();
     3904                vertexArray[i*2+1] = points[i].y();
    39073905            }
    39083906
     
    39593957}
    39603958
    3961 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
     3959Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
    39623960
    39633961void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
     
    40804078        case QPainterPath::MoveToElement:
    40814079            if (i != 0) {
    4082                 glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
     4080                glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
    40834081                glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
    40844082                tess_points.reset();
     
    41304128        } // end of switch
    41314129    }
    4132     glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
     4130    glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
    41334131    glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
    41344132    glDisableClientState(GL_VERTEX_ARRAY);
     
    43974395        }
    43984396
    4399         q_vertexType vertexArray[4*2];
    4400         q_vertexType texCoordArray[4*2];
     4397        GLfloat vertexArray[4*2];
     4398        GLfloat texCoordArray[4*2];
    44014399
    44024400        double offset_x = offset.x() / pm.width();
     
    44074405                                  tc_w + offset_x, tc_h + offset_y, texCoordArray);
    44084406
    4409         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    4410         glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     4407        glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     4408        glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
    44114409
    44124410        glEnableClientState(GL_VERTEX_ARRAY);
     
    44894487    }
    44904488
    4491     q_vertexType vertexArray[4*2];
    4492     q_vertexType texCoordArray[4*2];
     4489    GLfloat vertexArray[4*2];
     4490    GLfloat texCoordArray[4*2];
    44934491
    44944492    qt_add_rect_to_array(r, vertexArray);
    44954493    qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
    44964494
    4497     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    4498     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     4495    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     4496    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
    44994497
    45004498    glEnableClientState(GL_VERTEX_ARRAY);
     
    45614559    ~QGLGlyphCache();
    45624560    QGLGlyphCoord *lookup(QFontEngine *, glyph_t);
    4563     void cacheGlyphs(QGLContext *, const QTextItemInt &, const QVarLengthArray<glyph_t> &);
     4561    void cacheGlyphs(QGLContext *, QFontEngine *, glyph_t *glyphs, int numGlyphs);
    45644562    void cleanCache();
    45654563    void allocTexture(int width, int height, GLuint texture);
     
    47134711#endif
    47144712
    4715 void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti,
    4716                                 const QVarLengthArray<glyph_t> &glyphs)
     4713void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
     4714                                glyph_t *glyphs, int numGlyphs)
    47174715{
    47184716    QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context);
     
    47384736//         qDebug() << "new context" << context << font_cache;
    47394737        qt_context_cache.insert(context, font_cache);
    4740         if (context->isValid() && context->device()->devType() == QInternal::Widget) {
    4741             QWidget *widget = static_cast<QWidget *>(context->device());
    4742             connect(widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)));
     4738        if (context->isValid()) {
     4739            if (context->device()->devType() == QInternal::Widget) {
     4740                QWidget *widget = static_cast<QWidget *>(context->device());
     4741                connect(widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)));
     4742            }
    47434743            connect(QGLSignalProxy::instance(),
    47444744                    SIGNAL(aboutToDestroyContext(const QGLContext*)),
     
    47504750    Q_ASSERT(font_cache != 0);
    47514751
    4752     QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(ti.fontEngine);
     4752    QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine);
    47534753    QGLGlyphHash *cache = 0;
    47544754    if (cache_it == font_cache->constEnd()) {
    47554755        cache = new QGLGlyphHash;
    4756         font_cache->insert(ti.fontEngine, cache);
    4757         connect(ti.fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
     4756        font_cache->insert(fontEngine, cache);
     4757        connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
    47584758    } else {
    47594759        cache = cache_it.value();
     
    47624762
    47634763    quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32)
    4764                        | reinterpret_cast<quint64>(ti.fontEngine);
     4764                       | reinterpret_cast<quint64>(fontEngine);
    47654765    QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key);
    47664766    QGLFontTexture *font_tex;
     
    47684768        GLuint font_texture;
    47694769        glGenTextures(1, &font_texture);
    4770         GLint tex_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2);
     4770        GLint tex_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2);
    47714771        GLint tex_width = qt_next_power_of_two(tex_height*30); // ###
    47724772        GLint max_tex_size;
     
    47904790    }
    47914791
    4792     for (int i=0; i< glyphs.size(); ++i) {
     4792    for (int i=0; i< numGlyphs; ++i) {
    47934793        QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
    47944794        if (it == cache->constEnd()) {
    47954795            // render new glyph and put it in the cache
    4796             glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
     4796            glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
    47974797            int glyph_width = qRound(metrics.width.toReal())+2;
    4798             int glyph_height = qRound(ti.ascent.toReal() + ti.descent.toReal())+2;
     4798            int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2;
    47994799
    48004800            if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) {
    4801                 int strip_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2);
     4801                int strip_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2);
    48024802                font_tex->x_offset = x_margin;
    48034803                font_tex->y_offset += strip_height;
     
    48324832            }
    48334833
    4834             QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i]));
     4834            QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i]));
    48354835            glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
    48364836            glyph_width = glyph_im.width();
     
    49124912}
    49134913
     4914void QOpenGLPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
     4915{
     4916    Q_D(QOpenGLPaintEngine);
     4917
     4918    d->flushDrawQueue();
     4919
     4920    // make sure the glyphs we want to draw are in the cache
     4921    qt_glyph_cache()->cacheGlyphs(d->device->context(), textItem->fontEngine(), textItem->glyphs,
     4922                                  textItem->numGlyphs);
     4923
     4924    d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
     4925    qt_glColor4ubv(d->pen_color);
     4926    glEnable(GL_TEXTURE_2D);
     4927
     4928#ifdef Q_WS_QWS
     4929    // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want
     4930    // text rendering to update the alpha in the window surface.
     4931    // XXX: This may not be needed as this behavior does seem to be caused by driver bug
     4932    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
     4933#endif
     4934
     4935    // do the actual drawing
     4936    GLfloat vertexArray[4*2];
     4937    GLfloat texCoordArray[4*2];
     4938
     4939    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     4940    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
     4941
     4942    glEnableClientState(GL_VERTEX_ARRAY);
     4943    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     4944    bool antialias = !(textItem->fontEngine()->fontDef.styleStrategy & QFont::NoAntialias)
     4945                                   && (d->matrix.type() > QTransform::TxTranslate);
     4946    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
     4947    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
     4948
     4949    for (int i=0; i< textItem->numGlyphs; ++i) {
     4950        QGLGlyphCoord *g = qt_glyph_cache()->lookup(textItem->fontEngine(), textItem->glyphs[i]);
     4951
     4952        // we don't cache glyphs with no width/height
     4953        if (!g)
     4954            continue;
     4955
     4956        qreal x1, x2, y1, y2;
     4957        x1 = g->x;
     4958        y1 = g->y;
     4959        x2 = x1 + g->width;
     4960        y2 = y1 + g->height;
     4961
     4962        QPointF logical_pos((textItem->glyphPositions[i].x - g->x_offset).toReal(),
     4963                            (textItem->glyphPositions[i].y + g->y_offset).toReal());
     4964
     4965        qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray);
     4966        qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray);
     4967
     4968        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     4969    }
     4970
     4971    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
     4972    glDisableClientState(GL_VERTEX_ARRAY);
     4973
     4974    glDisable(GL_TEXTURE_2D);
     4975
     4976#ifdef Q_WS_QWS
     4977    // XXX: This may not be needed as this behavior does seem to be caused by driver bug
     4978    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     4979#endif
     4980
     4981}
     4982
    49144983void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
    49154984{
     
    49264995    }
    49274996
    4928     d->flushDrawQueue();
    4929 
    49304997    // add the glyphs used to the glyph texture cache
    49314998    QVarLengthArray<QFixedPoint> positions;
     
    49345001    ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
    49355002
    4936     // make sure the glyphs we want to draw are in the cache
    4937     qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs);
    4938 
    4939     d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
    4940     qt_glColor4ubv(d->pen_color);
    4941     glEnable(GL_TEXTURE_2D);
    4942 
    4943 #ifdef Q_WS_QWS
    4944     // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want
    4945     // text rendering to update the alpha in the window surface.
    4946     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
    4947     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
    4948 #endif
    4949 
    4950     // do the actual drawing
    4951     q_vertexType vertexArray[4*2];
    4952     q_vertexType texCoordArray[4*2];
    4953 
    4954     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    4955     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
    4956 
    4957     glEnableClientState(GL_VERTEX_ARRAY);
    4958     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    4959     bool antialias = !(ti.fontEngine->fontDef.styleStrategy & QFont::NoAntialias)
    4960                    && (d->matrix.type() > QTransform::TxTranslate);
    4961     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
    4962     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
    4963 
    4964     for (int i=0; i< glyphs.size(); ++i) {
    4965         QGLGlyphCoord *g = qt_glyph_cache()->lookup(ti.fontEngine, glyphs[i]);
    4966 
    4967         // we don't cache glyphs with no width/height
    4968         if (!g)
    4969             continue;
    4970 
    4971         qreal x1, x2, y1, y2;
    4972         x1 = g->x;
    4973         y1 = g->y;
    4974         x2 = x1 + g->width;
    4975         y2 = y1 + g->height;
    4976 
    4977         QPointF logical_pos((positions[i].x - g->x_offset).toReal(),
    4978                             (positions[i].y + g->y_offset).toReal());
    4979 
    4980         qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray);
    4981         qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray);
    4982 
    4983         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    4984     }
    4985 
    4986     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    4987     glDisableClientState(GL_VERTEX_ARRAY);
    4988 
    4989     glDisable(GL_TEXTURE_2D);
    4990 
    4991 #ifdef Q_WS_QWS
    4992     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
    4993     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    4994 #endif
     5003    {
     5004        QStaticTextItem staticTextItem;
     5005        staticTextItem.chars = const_cast<QChar *>(ti.chars);
     5006        staticTextItem.setFontEngine(ti.fontEngine);
     5007        staticTextItem.glyphs = glyphs.data();
     5008        staticTextItem.numChars = ti.num_chars;
     5009        staticTextItem.numGlyphs = glyphs.size();
     5010        staticTextItem.glyphPositions = positions.data();
     5011        drawStaticTextItem(&staticTextItem);
     5012    }
     5013
    49955014}
    49965015
     
    51665185    Q_UNUSED(maskOffset);
    51675186#else
    5168     q_vertexType vertexArray[8];
     5187    GLfloat vertexArray[8];
    51695188    qt_add_rect_to_array(rect, vertexArray);
    51705189
     
    51745193
    51755194
    5176 void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset)
     5195void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset)
    51775196{
    51785197#ifdef QT_OPENGL_ES
     
    51975216
    51985217        for (int i = 0; i < vertexCount; ++i) {
    5199             qreal x = vt2f(vertexArray[2 * i]);
    5200             qreal y = vt2f(vertexArray[2 * i + 1]);
     5218            qreal x = vertexArray[2 * i];
     5219            qreal y = vertexArray[2 * i + 1];
    52015220
    52025221            qreal tx, ty;
     
    52575276
    52585277    glEnableClientState(GL_VERTEX_ARRAY);
    5259     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     5278    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
    52605279    glEnable(GL_FRAGMENT_PROGRAM_ARB);
    52615280    GLuint program = qt_gl_program_cache()->getProgram(device->context(),
  • trunk/src/opengl/qpaintengine_opengl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    134134                   Qt::ImageConversionFlags conversionFlags);
    135135    void drawTextItem(const QPointF &p, const QTextItem &ti);
     136    void drawStaticTextItem(QStaticTextItem *staticTextItem);
    136137
    137138    void drawEllipse(const QRectF &rect);
  • trunk/src/opengl/qpixmapdata_gl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    368368
    369369void QGLPixmapData::fromImage(const QImage &image,
    370                               Qt::ImageConversionFlags /*flags*/)
     370                              Qt::ImageConversionFlags flags)
    371371{
    372372    if (image.size() == QSize(w, h))
     
    382382            format = QImage::Format_RGB16;
    383383
    384         if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
     384        if (image.hasAlphaChannel()
     385            && ((flags & Qt::NoOpaqueDetection)
     386                || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()))
    385387            format = QImage::Format_ARGB32_Premultiplied;;
    386388
     
    471473void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
    472474{
    473     if (data->classId() != QPixmapData::OpenGLClass) {
     475    if (data->classId() != QPixmapData::OpenGLClass || !static_cast<const QGLPixmapData *>(data)->useFramebufferObjects()) {
    474476        QPixmapData::copy(data, rect);
    475477        return;
    476478    }
    477479
    478     // can be optimized to do a framebuffer blit or similar ...
    479     QPixmapData::copy(data, rect);
     480    const QGLPixmapData *other = static_cast<const QGLPixmapData *>(data);
     481    if (other->m_renderFbo) {
     482        QGLShareContextScope ctx(qt_gl_share_widget()->context());
     483
     484        resize(rect.width(), rect.height());
     485        m_hasAlpha = other->m_hasAlpha;
     486        ensureCreated();
     487
     488        if (!ctx->d_ptr->fbo)
     489            glGenFramebuffers(1, &ctx->d_ptr->fbo);
     490
     491        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
     492        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     493                GL_TEXTURE_2D, m_texture.id, 0);
     494
     495        if (!other->m_renderFbo->isBound())
     496            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, other->m_renderFbo->handle());
     497
     498        glDisable(GL_SCISSOR_TEST);
     499        if (ctx->d_ptr->active_engine && ctx->d_ptr->active_engine->type() == QPaintEngine::OpenGL2)
     500            static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine)->invalidateState();
     501
     502        glBlitFramebufferEXT(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(),
     503                0, 0, w, h,
     504                GL_COLOR_BUFFER_BIT,
     505                GL_NEAREST);
     506
     507        glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
     508    } else {
     509        QPixmapData::copy(data, rect);
     510    }
    480511}
    481512
     
    622653}
    623654
    624 bool QGLPixmapData::useFramebufferObjects()
     655bool QGLPixmapData::useFramebufferObjects() const
    625656{
    626657    return QGLFramebufferObject::hasOpenGLFramebufferObjects()
    627658           && QGLFramebufferObject::hasOpenGLFramebufferBlit()
    628            && qt_gl_preferGL2Engine();
     659           && qt_gl_preferGL2Engine()
     660           && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps
    629661}
    630662
     
    708740}
    709741
    710 extern int qt_defaultDpiX();
    711 extern int qt_defaultDpiY();
     742Q_DECL_IMPORT extern int qt_defaultDpiX();
     743Q_DECL_IMPORT extern int qt_defaultDpiY();
    712744
    713745int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
  • trunk/src/opengl/qpixmapdata_gl_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9797
    9898
    99 class QGLPixmapData : public QPixmapData
     99class Q_OPENGL_EXPORT QGLPixmapData : public QPixmapData
    100100{
    101101public:
     
    146146    QSize size() const { return QSize(w, h); }
    147147
    148     static bool useFramebufferObjects();
     148    bool useFramebufferObjects() const;
    149149
    150150    QImage fillImage(const QColor &color) const;
     
    169169
    170170    friend class QGLPixmapGLPaintDevice;
     171    friend class QMeeGoPixmapData;
     172    friend class QMeeGoLivePixmapData;
    171173};
    172174
  • trunk/src/opengl/qpixmapdata_x11gl_egl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4242#include <QDebug>
    4343
    44 #include <private/qgl_p.h>
    45 #include <private/qegl_p.h>
    46 #include <private/qeglproperties_p.h>
    47 
    48 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
    49 #include <private/qpaintengineex_opengl2_p.h>
     44#include <QtGui/private/qt_x11_p.h>
     45#include <QtGui/private/qegl_p.h>
     46#include <QtGui/private/qeglproperties_p.h>
     47#include <QtGui/private/qeglcontext_p.h>
     48
     49#if !defined(QT_OPENGL_ES_1)
     50#include <QtOpenGL/private/qpaintengineex_opengl2_p.h>
    5051#endif
    5152
    5253#ifndef QT_OPENGL_ES_2
    53 #include <private/qpaintengine_opengl_p.h>
    54 #endif
     54#include <QtOpenGL/private/qpaintengine_opengl_p.h>
     55#endif
     56
     57#include <QtOpenGL/private/qgl_p.h>
     58#include <QtOpenGL/private/qgl_egl_p.h>
    5559
    5660#include "qpixmapdata_x11gl_p.h"
     
    5862QT_BEGIN_NAMESPACE
    5963
    60 extern EGLConfig qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly); // in qgl_x11egl.cpp
    61 extern bool qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly); // in qgl_x11egl.cpp
    62 
    63 // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need
    64 // different contexts:
    65 static EGLContext qPixmapARGBSharedEglContext = EGL_NO_CONTEXT;
    66 static EGLContext qPixmapRGBSharedEglContext = EGL_NO_CONTEXT;
    67 
    68 bool QX11GLPixmapData::hasX11GLPixmaps()
    69 {
    70     static bool checkedForX11Pixmaps = false;
    71     static bool haveX11Pixmaps = false;
    72 
    73     if (checkedForX11Pixmaps)
    74         return haveX11Pixmaps;
    75 
    76     checkedForX11Pixmaps = true;
    77 
    78     QX11PixmapData *argbPixmapData = 0;
    79     QX11PixmapData *rgbPixmapData = 0;
    80     do {
    81         if (qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty())
    82             break;
    83 
    84         // Check we actually have EGL configs which support pixmaps
    85         EGLConfig argbConfig = qt_chooseEGLConfigForPixmap(true, false);
    86         EGLConfig rgbConfig = qt_chooseEGLConfigForPixmap(false, false);
    87 
    88         if (argbConfig == 0 || rgbConfig == 0)
    89             break;
    90 
    91         // Create the shared contexts:
    92         eglBindAPI(EGL_OPENGL_ES_API);
    93         EGLint contextAttribs[] = {
    94 #if defined(QT_OPENGL_ES_2)
    95             EGL_CONTEXT_CLIENT_VERSION, 2,
    96 #endif
    97             EGL_NONE
    98         };
    99         qPixmapARGBSharedEglContext = eglCreateContext(QEglContext::display(),
    100                                                        argbConfig, 0, contextAttribs);
    101 
    102         if (argbConfig == rgbConfig) {
    103             // If the configs are the same, we can re-use the same context.
    104             qPixmapRGBSharedEglContext = qPixmapARGBSharedEglContext;
    105         } else {
    106             qPixmapRGBSharedEglContext = eglCreateContext(QEglContext::display(),
    107                                                            rgbConfig, 0, contextAttribs);
    108         }
    109 
    110         argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
    111         argbPixmapData->resize(100, 100);
    112         argbPixmapData->fill(Qt::transparent); // Force ARGB
    113 
    114         if (!qt_createEGLSurfaceForPixmap(argbPixmapData, false))
    115             break;
    116 
    117         haveX11Pixmaps = eglMakeCurrent(QEglContext::display(),
    118                                         (EGLSurface)argbPixmapData->gl_surface,
    119                                         (EGLSurface)argbPixmapData->gl_surface,
    120                                         qPixmapARGBSharedEglContext);
    121         if (!haveX11Pixmaps) {
    122             EGLint err = eglGetError();
    123             qWarning() << "Unable to make pixmap config current:" << err << QEglContext::errorString(err);
    124             break;
    125         }
    126 
    127         // If the ARGB & RGB configs are the same, we don't need to check RGB too
    128         if (haveX11Pixmaps && (argbConfig != rgbConfig)) {
    129             rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
    130             rgbPixmapData->resize(100, 100);
     64
     65class QX11GLSharedContexts
     66{
     67public:
     68    QX11GLSharedContexts()
     69        : rgbContext(0)
     70        , argbContext(0)
     71        , sharedQGLContext(0)
     72        , sharePixmap(0)
     73    {
     74        EGLint rgbConfigId;
     75        EGLint argbConfigId;
     76
     77        do {
     78            EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable);
     79            EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL,
     80                                                       QEgl::Renderable | QEgl::Translucent);
     81
     82            eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId);
     83            eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId);
     84
     85            rgbContext = new QEglContext;
     86            rgbContext->setConfig(rgbConfig);
     87            rgbContext->createContext();
     88
     89            if (!rgbContext->isValid())
     90                break;
     91
     92            // If the RGB & ARGB configs are the same, use the same egl context for both:
     93            if (rgbConfig == argbConfig)
     94                argbContext = rgbContext;
     95
     96            // Otherwise, create a separate context to be used for ARGB pixmaps:
     97            if (!argbContext) {
     98                argbContext = new QEglContext;
     99                argbContext->setConfig(argbConfig);
     100                bool success = argbContext->createContext(rgbContext);
     101                if (!success) {
     102                    qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared");
     103                    success = argbContext->createContext();
     104                    if (!success)
     105                        argbContext = rgbContext; // Might work, worth a shot at least.
     106                }
     107            }
     108
     109            if (!argbContext->isValid())
     110                break;
     111
     112            // Create the pixmap which will be used to create the egl surface for the share QGLContext
     113            QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
     114            rgbPixmapData->resize(8, 8);
    131115            rgbPixmapData->fill(Qt::red);
    132 
    133             // Try to actually create an EGL pixmap surface
    134             if (!qt_createEGLSurfaceForPixmap(rgbPixmapData, false))
    135                 break;
    136 
    137             haveX11Pixmaps = eglMakeCurrent(QEglContext::display(),
    138                                             (EGLSurface)rgbPixmapData->gl_surface,
    139                                             (EGLSurface)rgbPixmapData->gl_surface,
    140                                             qPixmapRGBSharedEglContext);
    141             if (!haveX11Pixmaps) {
    142                 EGLint err = eglGetError();
    143                 qWarning() << "Unable to make pixmap config current:" << err << QEglContext::errorString(err);
     116            sharePixmap = new QPixmap(rgbPixmapData);
     117            EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig);
     118            rgbPixmapData->gl_surface = (void*)sharePixmapSurface;
     119
     120            // Create the actual QGLContext which will be used for sharing
     121            sharedQGLContext = new QGLContext(QX11GLPixmapData::glFormat());
     122            sharedQGLContext->d_func()->eglContext = rgbContext;
     123            sharedQGLContext->d_func()->eglSurface = sharePixmapSurface;
     124            sharedQGLContext->d_func()->valid = true;
     125            qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig);
     126
     127
     128            valid = rgbContext->makeCurrent(sharePixmapSurface);
     129
     130            // If the ARGB & RGB configs are different, check ARGB works too:
     131            if (argbConfig != rgbConfig) {
     132                QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType);
     133                argbPixmapData->resize(8, 8);
     134                argbPixmapData->fill(Qt::transparent); // Force ARGB
     135                QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope
     136                EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig);
     137                valid = argbContext->makeCurrent(argbPixmapSurface);
     138                argbContext->doneCurrent();
     139                eglDestroySurface(QEgl::display(), argbPixmapSurface);
     140                argbPixmapData->gl_surface = 0;
     141            }
     142
     143            if (!valid) {
     144                qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString();
    144145                break;
    145146            }
     147
     148            // The pixmap surface destruction hooks are installed by QGLTextureCache, so we
     149            // must make sure this is instanciated:
     150            QGLTextureCache::instance();
     151        } while(0);
     152
     153        if (!valid)
     154            cleanup();
     155        else
     156            qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId);
     157
     158    }
     159
     160    ~QX11GLSharedContexts() {
     161        cleanup();
     162    }
     163
     164    void cleanup() {
     165        if (sharedQGLContext) {
     166            delete sharedQGLContext;
     167            sharedQGLContext = 0;
    146168        }
    147     } while (0);
    148 
    149     if (qPixmapARGBSharedEglContext || qPixmapRGBSharedEglContext) {
    150         eglMakeCurrent(QEglContext::display(),
    151                        EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    152     }
    153 
    154     if (argbPixmapData) {
    155         if (argbPixmapData->gl_surface)
    156             QGLContextPrivate::destroyGlSurfaceForPixmap(argbPixmapData);
    157         delete argbPixmapData;
    158         argbPixmapData = 0;
    159     }
    160     if (rgbPixmapData) {
    161         if (rgbPixmapData->gl_surface)
    162             QGLContextPrivate::destroyGlSurfaceForPixmap(rgbPixmapData);
    163         delete rgbPixmapData;
    164         rgbPixmapData = 0;
    165     }
    166 
    167     if (!haveX11Pixmaps) {
    168         // Clean up the context(s) if we can't use X11GL pixmaps
    169         if (qPixmapARGBSharedEglContext != EGL_NO_CONTEXT)
    170             eglDestroyContext(QEglContext::display(), qPixmapARGBSharedEglContext);
    171 
    172         if (qPixmapRGBSharedEglContext != qPixmapARGBSharedEglContext &&
    173             qPixmapRGBSharedEglContext != EGL_NO_CONTEXT)
    174         {
    175             eglDestroyContext(QEglContext::display(), qPixmapRGBSharedEglContext);
     169        if (argbContext && argbContext != rgbContext)
     170            delete argbContext;
     171        argbContext = 0;
     172
     173        if (rgbContext) {
     174            delete rgbContext;
     175            rgbContext = 0;
    176176        }
    177         qPixmapRGBSharedEglContext = EGL_NO_CONTEXT;
    178         qPixmapARGBSharedEglContext = EGL_NO_CONTEXT;
    179     }
    180 
    181     if (haveX11Pixmaps)
    182         qDebug("QX11GLPixmapData is supported");
    183     else
    184         qDebug("QX11GLPixmapData is *NOT* being used");
    185 
    186     return haveX11Pixmaps;
     177
     178        // Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn
     179        // will destroy the egl surface:
     180        if (sharePixmap) {
     181            delete sharePixmap;
     182            sharePixmap = 0;
     183        }
     184    }
     185
     186    bool isValid() { return valid;}
     187
     188    // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need
     189    // different contexts:
     190    QEglContext *rgbContext;
     191    QEglContext *argbContext;
     192
     193    // The share context wraps the rgbContext and is used as the master of the context share
     194    // group. As all other contexts will have the same egl context (or a shared one if rgb != argb)
     195    // all QGLContexts will actually be sharing and can be in the same context group.
     196    QGLContext  *sharedQGLContext;
     197private:
     198    QPixmap     *sharePixmap;
     199    bool         valid;
     200};
     201
     202static void qt_cleanup_x11gl_share_contexts();
     203
     204Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts,
     205                                 {
     206                                     qAddPostRoutine(qt_cleanup_x11gl_share_contexts);
     207                                 })
     208
     209static void qt_cleanup_x11gl_share_contexts()
     210{
     211    qt_x11gl_share_contexts()->cleanup();
     212}
     213
     214
     215QX11GLSharedContexts* QX11GLPixmapData::sharedContexts()
     216{
     217    return qt_x11gl_share_contexts();
     218}
     219
     220bool QX11GLPixmapData::hasX11GLPixmaps()
     221{
     222    static bool checkedForX11GLPixmaps = false;
     223    static bool haveX11GLPixmaps = false;
     224
     225    if (checkedForX11GLPixmaps)
     226        return haveX11GLPixmaps;
     227
     228    haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid();
     229    checkedForX11GLPixmaps = true;
     230
     231    return haveX11GLPixmaps;
    187232}
    188233
     
    195240QX11GLPixmapData::~QX11GLPixmapData()
    196241{
    197 }
    198 
    199 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     242    if (ctx)
     243        delete ctx;
     244}
     245
     246
     247void QX11GLPixmapData::fill(const QColor &color)
     248{
     249    if (ctx) {
     250        ctx->makeCurrent();
     251        glFinish();
     252        eglWaitClient();
     253    }
     254
     255    QX11PixmapData::fill(color);
     256    XSync(X11->display, False);
     257
     258    if (ctx) {
     259        ctx->makeCurrent();
     260        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     261    }
     262}
     263
     264void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect)
     265{
     266    if (ctx) {
     267        ctx->makeCurrent();
     268        glFinish();
     269        eglWaitClient();
     270    }
     271
     272    QX11PixmapData::copy(data, rect);
     273    XSync(X11->display, False);
     274
     275    if (ctx) {
     276        ctx->makeCurrent();
     277        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     278    }
     279}
     280
     281bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect)
     282{
     283    if (ctx) {
     284        ctx->makeCurrent();
     285        glFinish();
     286        eglWaitClient();
     287    }
     288
     289    bool success = QX11PixmapData::scroll(dx, dy, rect);
     290    XSync(X11->display, False);
     291
     292    if (ctx) {
     293        ctx->makeCurrent();
     294        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     295    }
     296
     297    return success;
     298}
     299
     300#if !defined(QT_OPENGL_ES_1)
    200301Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine)
    201302#endif
     
    211312    if (!ctx) {
    212313        ctx = new QGLContext(glFormat());
    213         if (ctx->d_func()->eglContext == 0)
    214             ctx->d_func()->eglContext = new QEglContext();
    215         ctx->d_func()->eglContext->setApi(QEgl::OpenGL);
    216         ctx->d_func()->eglContext->setContext(hasAlphaChannel() ? qPixmapARGBSharedEglContext
    217                                                                 : qPixmapRGBSharedEglContext);
     314        Q_ASSERT(ctx->d_func()->eglContext == 0);
     315        ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext;
     316
     317        // While we use a separate QGLContext for each pixmap, the underlying QEglContext is
     318        // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking
     319        // each pixmap's QGLContext is sharing with this central one. The only place this is
     320        // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing.
     321        ctx->d_func()->sharing = true;
     322        QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext);
     323
     324        // Update the glFormat for the QGLContext:
     325        qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config());
    218326    }
    219327
    220328    QPaintEngine* engine;
    221329
    222 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     330#if defined(QT_OPENGL_ES_1)
    223331    engine = qt_gl_pixmap_engine();
    224332#elif defined(QT_OPENGL_ES_2)
     
    237345        qWarning("Pixmap paint engine already active");
    238346
    239 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     347#if defined(QT_OPENGL_ES_1)
    240348        engine = new QOpenGLPaintEngine;
    241349#elif defined(QT_OPENGL_ES_2)
     
    258366{
    259367//    qDebug("QX11GLPixmapData::beginPaint()");
     368    // TODO: Check to see if the surface is renderable
    260369    if ((EGLSurface)gl_surface == EGL_NO_SURFACE) {
    261         qt_createEGLSurfaceForPixmap(this, false);
    262         ctx->d_func()->eglSurface = (EGLSurface)gl_surface;
    263         ctx->d_func()->valid = true; // ;-)
     370        QPixmap tmpPixmap(this);
     371        EGLConfig cfg = ctx->d_func()->eglContext->config();
     372        Q_ASSERT(cfg != QEGL_NO_CONFIG);
     373
     374//        qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID));
     375        EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg);
     376        if (surface == EGL_NO_SURFACE) {
     377            qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString();
     378            return;
     379        }
     380        gl_surface = (void*)surface;
     381        ctx->d_func()->eglSurface = surface;
     382        ctx->d_func()->valid = true;
    264383    }
    265384    QGLPaintDevice::beginPaint();
    266385}
    267386
    268 void QX11GLPixmapData::endPaint()
    269 {
    270     glFinish();
    271     QGLPaintDevice::endPaint();
    272 }
    273 
    274387QGLContext* QX11GLPixmapData::context() const
    275388{
  • trunk/src/opengl/qpixmapdata_x11gl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6060#include <qgl.h>
    6161
     62#ifndef QT_NO_EGL
     63#include <QtGui/private/qeglcontext_p.h>
     64#endif
     65
    6266QT_BEGIN_NAMESPACE
     67
     68class QX11GLSharedContexts;
    6369
    6470class QX11GLPixmapData : public QX11PixmapData, public QGLPaintDevice
     
    6874    virtual ~QX11GLPixmapData();
    6975
     76    // Re-implemented from QX11PixmapData:
     77    void fill(const QColor &color);
     78    void copy(const QPixmapData *data, const QRect &rect);
     79    bool scroll(int dx, int dy, const QRect &rect);
     80
    7081    // Re-implemented from QGLPaintDevice
    7182    QPaintEngine* paintEngine() const; // Also re-implements QX11PixmapData::paintEngine
    7283    void beginPaint();
    73     void endPaint();
    7484    QGLContext* context() const;
    7585    QSize size() const;
     
    7787    static bool hasX11GLPixmaps();
    7888    static QGLFormat glFormat();
     89    static QX11GLSharedContexts* sharedContexts();
     90
    7991private:
    8092    mutable QGLContext* ctx;
  • trunk/src/opengl/qwindowsurface_gl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8383#endif
    8484
    85 #ifdef QT_OPENGL_ES_1_CL
    86 #include "qgl_cl_p.h"
    87 #endif
    88 
    89 #ifdef QT_OPENGL_ES
    90 #include <private/qegl_p.h>
     85#ifndef QT_NO_EGL
     86#include <private/qeglcontext_p.h>
    9187#endif
    9288
     
    9995extern Q_GUI_EXPORT bool qt_win_owndc_required;
    10096#endif
    101 QGLGraphicsSystem::QGLGraphicsSystem()
    102     : QGraphicsSystem()
     97QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL)
     98    : QGraphicsSystem(), m_useX11GL(useX11GL)
    10399{
    104100#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     
    195191        if (!initializing && !widget && !cleanedUp) {
    196192            initializing = true;
    197             widget = new QGLWidget;
    198             // We dont need this internal widget to appear in QApplication::topLevelWidgets()
     193
     194            widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer));
     195            widget->resize(1, 1);
     196
     197            // We don't need this internal widget to appear in QApplication::topLevelWidgets()
    199198            if (QWidgetPrivate::allWidgets)
    200199                QWidgetPrivate::allWidgets->remove(widget);
     
    204203    }
    205204
     205    // destroys the share widget and prevents recreation
    206206    void cleanup() {
    207207        QGLWidget *w = widget;
     
    211211    }
    212212
     213    // destroys the share widget, but allows it to be recreated later on
     214    void destroy() {
     215        if (cleanedUp)
     216            return;
     217
     218        QGLWidget *w = widget;
     219
     220        // prevent potential recursions
     221        cleanedUp = true;
     222        widget = 0;
     223        delete w;
     224        cleanedUp = false;
     225    }
     226
    213227    static bool cleanedUp;
    214228
     
    238252}
    239253
     254void qt_destroy_gl_share_widget()
     255{
     256    _qt_gl_share_widget()->destroy();
     257}
    240258
    241259struct QGLWindowSurfacePrivate
     
    250268    int destructive_swap_buffers : 1;
    251269    int geometry_updated : 1;
     270    int did_paint : 1;
    252271
    253272    QGLContext *ctx;
     
    257276    QRegion paintedRegion;
    258277    QSize size;
     278
     279    QSize textureSize;
    259280
    260281    QList<QImage> buffers;
     
    264285
    265286QGLFormat QGLWindowSurface::surfaceFormat;
     287QGLWindowSurface::SwapMode QGLWindowSurface::swapBehavior = QGLWindowSurface::AutomaticSwap;
    266288
    267289void QGLWindowSurfaceGLPaintDevice::endPaint()
     
    299321    d_ptr->fbo = 0;
    300322    d_ptr->ctx = 0;
     323    d_ptr->tex_id = 0;
    301324#if defined (QT_OPENGL_ES_2)
    302325    d_ptr->tried_fbo = true;
     
    310333    d_ptr->q_ptr = this;
    311334    d_ptr->geometry_updated = false;
     335    d_ptr->did_paint = false;
    312336}
    313337
     
    328352void QGLWindowSurface::deleted(QObject *object)
    329353{
    330     // Make sure that the fbo is destroyed before destroying its context.
    331     delete d_ptr->fbo;
    332     d_ptr->fbo = 0;
    333 
    334354    QWidget *widget = qobject_cast<QWidget *>(object);
    335355    if (widget) {
     356        if (widget == window()) {
     357            // Make sure that the fbo is destroyed before destroying its context.
     358            delete d_ptr->fbo;
     359            d_ptr->fbo = 0;
     360        }
     361
    336362        QWidgetPrivate *widgetPrivate = widget->d_func();
    337363        if (widgetPrivate->extraData()) {
     
    355381        return;
    356382
    357     QGLContext *ctx = new QGLContext(surfaceFormat, widget);
     383    QGLContext *ctx = NULL;
     384
     385    // For translucent top-level widgets we need alpha in the format.
     386    if (widget->testAttribute(Qt::WA_TranslucentBackground)) {
     387        QGLFormat modFormat(surfaceFormat);
     388        modFormat.setSampleBuffers(false);
     389        modFormat.setSamples(0);
     390        modFormat.setAlpha(true);
     391        ctx = new QGLContext(modFormat, widget);
     392    } else
     393        ctx = new QGLContext(surfaceFormat, widget);
     394
    358395    ctx->create(qt_gl_share_widget()->context());
    359396
    360 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
    361     // Create the EGL surface to draw into.  QGLContext::chooseContext()
    362     // does not do this for X11/EGL, but does do it for other platforms.
    363     // This probably belongs in qgl_x11egl.cpp.
    364     QGLContextPrivate *ctxpriv = ctx->d_func();
    365     ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(widget);
    366     if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
    367         qWarning() << "hijackWindow() could not create EGL surface";
    368     }
    369     qDebug("QGLWindowSurface - using EGLConfig %d", reinterpret_cast<int>(ctxpriv->eglContext->config()));
     397#ifndef QT_NO_EGL
     398    static bool checkedForNOKSwapRegion = false;
     399    static bool haveNOKSwapRegion = false;
     400
     401    if (!checkedForNOKSwapRegion) {
     402        haveNOKSwapRegion = QEgl::hasExtension("EGL_NOK_swap_region2");
     403        checkedForNOKSwapRegion = true;
     404
     405        if (haveNOKSwapRegion)
     406            qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates.";
     407    }
     408
     409    if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED &&
     410        ! haveNOKSwapRegion)
     411        setPartialUpdateSupport(false); // Force full-screen updates
     412    else
     413        setPartialUpdateSupport(true);
    370414#endif
    371415
     
    398442    QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
    399443    ctx->makeCurrent();
     444
     445    Q_ASSERT(d_ptr->fbo);
    400446    return d_ptr->fbo;
    401447}
     
    405451void QGLWindowSurface::beginPaint(const QRegion &)
    406452{
     453    if (!context())
     454        return;
     455
     456    int clearFlags = 0;
     457
     458    if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
     459        clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
     460    else if (context()->format().alpha())
     461        clearFlags = GL_COLOR_BUFFER_BIT;
     462
     463    if (clearFlags) {
     464        glClearColor(0.0, 0.0, 0.0, 0.0);
     465        glClear(clearFlags);
     466    }
     467
     468    d_ptr->did_paint = true;
    407469}
    408470
     
    415477}
    416478
     479static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect)
     480{
     481    glDisable(GL_DEPTH_TEST);
     482    glDisable(GL_SCISSOR_TEST);
     483    glDisable(GL_BLEND);
     484
     485    glViewport(0, 0, viewport.width(), viewport.height());
     486
     487    QGLShaderProgram *blitProgram =
     488        QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
     489    blitProgram->bind();
     490    blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
     491
     492    // The shader manager's blit program does not multiply the
     493    // vertices by the pmv matrix, so we need to do the effect
     494    // of the orthographic projection here ourselves.
     495    QRectF r;
     496    qreal w = viewport.width();
     497    qreal h = viewport.height();
     498    r.setLeft((targetRect.left() / w) * 2.0f - 1.0f);
     499    if (targetRect.right() == (viewport.width() - 1))
     500        r.setRight(1.0f);
     501    else
     502        r.setRight((targetRect.right() / w) * 2.0f - 1.0f);
     503    r.setBottom((targetRect.top() / h) * 2.0f - 1.0f);
     504    if (targetRect.bottom() == (viewport.height() - 1))
     505        r.setTop(1.0f);
     506    else
     507        r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f);
     508
     509    drawTexture(r, texture, texSize, sourceRect);
     510}
     511
     512
    417513void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
    418514{
    419     if (context() && widget != window()) {
    420         qWarning("No native child widget support in GL window surface without FBOs or pixel buffers");
    421         return;
    422     }
    423 
    424515    //### Find out why d_ptr->geometry_updated isn't always false.
    425516    // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either
     
    428519        return;
    429520
     521    // did_paint is set to true in ::beginPaint. ::beginPaint means that we
     522    // at least cleared the background (= painted something). In EGL API it's a
     523    // mistake to call swapBuffers if nothing was painted unless
     524    // EGL_BUFFER_PRESERVED is set. This check protects the flush func from
     525    // being executed if it's for nothing.
     526    if (!hasPartialUpdateSupport() && !d_ptr->did_paint)
     527        return;
     528
    430529    QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
    431530    Q_ASSERT(parent);
     
    444543    const GLenum target = GL_TEXTURE_2D;
    445544    Q_UNUSED(target);
     545
     546    if (QGLWindowSurface::swapBehavior == QGLWindowSurface::KillSwap)
     547        return;
    446548
    447549    if (context()) {
     
    492594            }
    493595#endif
     596            bool doingPartialUpdate = false;
     597            if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AutomaticSwap)
     598                doingPartialUpdate = hasPartialUpdateSupport() && br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2;
     599            else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysFullSwap)
     600                doingPartialUpdate = false;
     601            else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysPartialSwap)
     602                doingPartialUpdate = hasPartialUpdateSupport();
     603
     604            QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext);
     605            if (widget != window()) {
     606                if (initializeOffscreenTexture(window()->size()))
     607                    qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss";
     608                glBindTexture(target, d_ptr->tex_id);
     609
     610                const uint bottom = window()->height() - (br.y() + br.height());
     611                glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
     612
     613                glBindTexture(target, 0);
     614
     615                ctx->makeCurrent();
     616                if (doingPartialUpdate)
     617                    blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br);
     618                else
     619                    blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset));
     620            }
     621
     622            if (doingPartialUpdate)
     623                ctx->d_func()->swapRegion(br);
     624            else
     625                ctx->swapBuffers();
     626
    494627            d_ptr->paintedRegion = QRegion();
    495             context()->swapBuffers();
    496628        } else {
    497629            glFlush();
     
    534666
    535667        if (window() == parent || d_ptr->fbo->format().samples() <= 1) {
    536             // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     668            if (ctx->d_ptr->current_fbo != 0)
     669                glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     670
    537671            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle());
    538672
     
    567701            qgl_fbo_pool()->release(temp);
    568702        }
     703
     704        ctx->d_ptr->current_fbo = 0;
    569705    }
    570706#if !defined(QT_OPENGL_ES_2)
     
    613749        Q_UNUSED(target);
    614750
    615         GLuint texture = d_ptr->fbo->texture();
    616 
    617         glDisable(GL_DEPTH_TEST);
    618 
    619751        if (d_ptr->fbo->isBound())
    620752            d_ptr->fbo->release();
    621753
    622         glViewport(0, 0, size.width(), size.height());
    623 
    624         QGLShaderProgram *blitProgram =
    625             QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
    626         blitProgram->bind();
    627         blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
    628 
    629         // The shader manager's blit program does not multiply the
    630         // vertices by the pmv matrix, so we need to do the effect
    631         // of the orthographic projection here ourselves.
    632         QRectF r;
    633         qreal w = size.width() ? size.width() : 1.0f;
    634         qreal h = size.height() ? size.height() : 1.0f;
    635         r.setLeft((rect.left() / w) * 2.0f - 1.0f);
    636         if (rect.right() == (size.width() - 1))
    637             r.setRight(1.0f);
    638         else
    639             r.setRight((rect.right() / w) * 2.0f - 1.0f);
    640         r.setBottom((rect.top() / h) * 2.0f - 1.0f);
    641         if (rect.bottom() == (size.height() - 1))
    642             r.setTop(1.0f);
    643         else
    644             r.setTop((rect.bottom() / w) * 2.0f - 1.0f);
    645 
    646         drawTexture(r, texture, window()->size(), br);
     754        blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br);
    647755    }
    648756#endif
     
    652760    else
    653761        glFlush();
     762
     763    d_ptr->did_paint = false;
    654764}
    655765
     
    667777    d_ptr->geometry_updated = false;
    668778
    669 
    670779    QRect rect = geometry();
    671780    hijackWindow(window());
     
    688797    if (d_ptr->ctx) {
    689798#ifndef QT_OPENGL_ES_2
    690         if (d_ptr->destructive_swap_buffers) {
    691             glBindTexture(target, d_ptr->tex_id);
    692             glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    693             glBindTexture(target, 0);
    694         }
     799        if (d_ptr->destructive_swap_buffers)
     800            initializeOffscreenTexture(rect.size());
    695801#endif
    696802        return;
     
    772878
    773879#ifndef QT_OPENGL_ES_2
    774     if (d_ptr->destructive_swap_buffers) {
    775         glGenTextures(1, &d_ptr->tex_id);
    776         glBindTexture(target, d_ptr->tex_id);
    777         glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    778 
    779         glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    780         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    781         glBindTexture(target, 0);
    782     }
     880    if (d_ptr->destructive_swap_buffers)
     881        initializeOffscreenTexture(rect.size());
    783882#endif
    784883
     
    786885    d_ptr->ctx = ctx;
    787886    d_ptr->ctx->d_ptr->internal_context = true;
     887}
     888
     889bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size)
     890{
     891    if (size == d_ptr->textureSize)
     892        return false;
     893
     894    glGenTextures(1, &d_ptr->tex_id);
     895    glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id);
     896    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
     897
     898    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     899    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     900    glBindTexture(GL_TEXTURE_2D, 0);
     901
     902    d_ptr->textureSize = size;
     903    return true;
    788904}
    789905
     
    839955    }
    840956
    841     const q_vertexType tx1 = f2vt(src.left());
    842     const q_vertexType tx2 = f2vt(src.right());
    843     const q_vertexType ty1 = f2vt(src.top());
    844     const q_vertexType ty2 = f2vt(src.bottom());
    845 
    846     q_vertexType texCoordArray[4*2] = {
     957    const GLfloat tx1 = src.left();
     958    const GLfloat tx2 = src.right();
     959    const GLfloat ty1 = src.top();
     960    const GLfloat ty2 = src.bottom();
     961
     962    GLfloat texCoordArray[4*2] = {
    847963        tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1
    848964    };
    849965
    850     q_vertexType vertexArray[4*2];
    851     extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array); // qpaintengine_opengl.cpp
     966    GLfloat vertexArray[4*2];
     967    extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); // qpaintengine_opengl.cpp
    852968    qt_add_rect_to_array(rect, vertexArray);
    853969
    854970#if !defined(QT_OPENGL_ES_2)
    855     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    856     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     971    glVertexPointer(2, GL_FLOAT, 0, vertexArray);
     972    glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
    857973
    858974    glBindTexture(target, tex_id);
  • trunk/src/opengl/qwindowsurface_gl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6767struct QGLWindowSurfacePrivate;
    6868
     69Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget();
     70Q_OPENGL_EXPORT void qt_destroy_gl_share_widget();
     71
    6972class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice
    7073{
     
    7881};
    7982
    80 class QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice
     83class Q_OPENGL_EXPORT QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice
    8184{
    8285    Q_OBJECT
     
    100103    static QGLFormat surfaceFormat;
    101104
     105    enum SwapMode { AutomaticSwap, AlwaysFullSwap, AlwaysPartialSwap, KillSwap };
     106    static SwapMode swapBehavior;
     107
    102108private slots:
    103109    void deleted(QObject *object);
     
    105111private:
    106112    void hijackWindow(QWidget *widget);
     113    bool initializeOffscreenTexture(const QSize &size);
    107114
    108115    QGLWindowSurfacePrivate *d_ptr;
  • trunk/src/opengl/qwindowsurface_x11gl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5252
    5353QX11GLWindowSurface::QX11GLWindowSurface(QWidget* window)
    54     : QWindowSurface(window), m_GC(0), m_window(window)
     54    : QWindowSurface(window), m_windowGC(0), m_pixmapGC(0), m_window(window)
    5555{
    5656}
     
    5858QX11GLWindowSurface::~QX11GLWindowSurface()
    5959{
    60     if (m_GC)
    61         XFree(m_GC);
     60    if (m_windowGC)
     61        XFree(m_windowGC);
     62    if (m_pixmapGC)
     63        XFree(m_pixmapGC);
    6264}
    6365
     
    7173void QX11GLWindowSurface::flush(QWidget *widget, const QRegion &widgetRegion, const QPoint &offset)
    7274{
    73 //    qDebug("QX11GLWindowSurface::flush()");
    74     QTime startTime = QTime::currentTime();
     75    // We don't need to know the widget which initiated the flush. Instead we just use the offset
     76    // to translate the widgetRegion:
     77    Q_UNUSED(widget);
     78
    7579    if (m_backBuffer.isNull()) {
    76         qDebug("QHarmattanWindowSurface::flush() - backBuffer is null, not flushing anything");
     80        qDebug("QX11GLWindowSurface::flush() - backBuffer is null, not flushing anything");
    7781        return;
    7882    }
    7983
    80     QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft();
    81     QRegion windowRegion(widgetRegion);
    82     QRect boundingRect = widgetRegion.boundingRect();
    83     if (!widgetOffset.isNull())
    84         windowRegion.translate(-widgetOffset);
    85     QRect windowBoundingRect = windowRegion.boundingRect();
     84    Q_ASSERT(window()->size() != m_backBuffer.size());
     85
     86    // Wait for all GL rendering to the back buffer pixmap to complete before trying to
     87    // copy it to the window. We do this by making sure the pixmap's context is current
     88    // and then call eglWaitClient. The EGL 1.4 spec says eglWaitClient doesn't have to
     89    // block, just that "All rendering calls...are guaranteed to be executed before native
     90    // rendering calls". This makes it potentially less expensive than glFinish.
     91    QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
     92    if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
     93        ctx->makeCurrent();
     94    eglWaitClient();
     95
     96    if (m_windowGC == 0) {
     97        XGCValues attribs;
     98        attribs.graphics_exposures = False;
     99        m_windowGC = XCreateGC(X11->display, m_window->handle(), GCGraphicsExposures, &attribs);
     100    }
    86101
    87102    int rectCount;
    88     XRectangle *rects = (XRectangle *)qt_getClipRects(windowRegion, rectCount);
     103    XRectangle *rects = (XRectangle *)qt_getClipRects(widgetRegion, rectCount);
    89104    if (rectCount <= 0)
    90105        return;
    91 //         qDebug() << "XSetClipRectangles";
    92 //         for  (int i = 0; i < num; ++i)
    93 //             qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
    94 
    95     if (m_GC == 0) {
    96         m_GC = XCreateGC(X11->display, m_window->handle(), 0, 0);
    97         XSetGraphicsExposures(X11->display, m_GC, False);
    98     }
    99 
    100     XSetClipRectangles(X11->display, m_GC, 0, 0, rects, rectCount, YXBanded);
    101     XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_GC,
    102               boundingRect.x() + offset.x(), boundingRect.y() + offset.y(),
    103               boundingRect.width(), boundingRect.height(),
    104               windowBoundingRect.x(), windowBoundingRect.y());
     106
     107    XSetClipRectangles(X11->display, m_windowGC, 0, 0, rects, rectCount, YXBanded);
     108
     109    QRect dirtyRect = widgetRegion.boundingRect().translated(-offset);
     110    XCopyArea(X11->display, m_backBuffer.handle(), m_window->handle(), m_windowGC,
     111              dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(),
     112              dirtyRect.x(), dirtyRect.y());
     113
     114    // Make sure the blit of the update from the back buffer to the window completes
     115    // before allowing rendering to start again to the back buffer. Otherwise the GPU
     116    // might start rendering to the back buffer again while the blit takes place.
     117    eglWaitNative(EGL_CORE_NATIVE_ENGINE);
    105118}
    106119
     
    108121{
    109122    if (rect.width() > m_backBuffer.size().width() || rect.height() > m_backBuffer.size().height()) {
     123        QX11GLPixmapData *pd = new QX11GLPixmapData;
    110124        QSize newSize = rect.size();
    111 //        QSize newSize(1024,512);
    112         qDebug() << "QX11GLWindowSurface::setGeometry() - creating a pixmap of size" << newSize;
    113         QX11GLPixmapData *pd = new QX11GLPixmapData;
    114125        pd->resize(newSize.width(), newSize.height());
    115126        m_backBuffer = QPixmap(pd);
    116     }
    117 
    118 //    if (gc)
    119 //        XFreeGC(X11->display, gc);
    120 //    gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0);
    121 //    XSetGraphicsExposures(X11->display, gc, False);
     127        if (window()->testAttribute(Qt::WA_TranslucentBackground))
     128            m_backBuffer.fill(Qt::transparent);
     129        if (m_pixmapGC) {
     130            XFreeGC(X11->display, m_pixmapGC);
     131            m_pixmapGC = 0;
     132        }
     133    }
     134
    122135    QWindowSurface::setGeometry(rect);
    123136}
     
    125138bool QX11GLWindowSurface::scroll(const QRegion &area, int dx, int dy)
    126139{
    127     Q_UNUSED(area);
    128     Q_UNUSED(dx);
    129     Q_UNUSED(dy);
    130     return false;
    131 }
    132 
    133 /*
    134 void QX11GLWindowSurface::beginPaint(const QRegion &region)
    135 {
    136 }
    137 
    138 void QX11GLWindowSurface::endPaint(const QRegion &region)
    139 {
    140 }
    141 
    142 QImage *QX11GLWindowSurface::buffer(const QWidget *widget)
    143 {
    144 }
    145 */
     140    if (m_backBuffer.isNull())
     141        return false;
     142
     143    Q_ASSERT(m_backBuffer.data_ptr()->classId() == QPixmapData::X11Class);
     144
     145    // Make sure all GL rendering is complete before starting the scroll operation:
     146    QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.data_ptr().data())->context();
     147    if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
     148        ctx->makeCurrent();
     149    eglWaitClient();
     150
     151    if (!m_pixmapGC)
     152        m_pixmapGC = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
     153
     154    foreach (const QRect& rect, area.rects()) {
     155        XCopyArea(X11->display, m_backBuffer.handle(), m_backBuffer.handle(), m_pixmapGC,
     156                  rect.x(), rect.y(), rect.width(), rect.height(),
     157                  rect.x()+dx, rect.y()+dy);
     158    }
     159
     160    // Make sure the scroll operation is complete before allowing GL rendering to resume
     161    eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     162
     163    return true;
     164}
     165
     166
     167QPixmap QX11GLWindowSurface::grabWidget(const QWidget *widget, const QRect& rect) const
     168{
     169    if (!widget || m_backBuffer.isNull())
     170        return QPixmap();
     171
     172    QRect srcRect;
     173
     174    // make sure the rect is inside the widget & clip to widget's rect
     175    if (!rect.isEmpty())
     176        srcRect = rect & widget->rect();
     177    else
     178        srcRect = widget->rect();
     179
     180    if (srcRect.isEmpty())
     181        return QPixmap();
     182
     183    // If it's a child widget we have to translate the coordinates
     184    if (widget != window())
     185        srcRect.translate(widget->mapTo(window(), QPoint(0, 0)));
     186
     187    QPixmap::x11SetDefaultScreen(widget->x11Info().screen());
     188
     189    QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType);
     190    pmd->resize(srcRect.width(), srcRect.height());
     191    QPixmap px(pmd);
     192
     193    GC tmpGc = XCreateGC(X11->display, m_backBuffer.handle(), 0, 0);
     194
     195    // Make sure all GL rendering is complete before copying the window
     196    QGLContext* ctx = static_cast<QX11GLPixmapData*>(m_backBuffer.pixmapData())->context();
     197    if (QGLContext::currentContext() != ctx && ctx && ctx->isValid())
     198        ctx->makeCurrent();
     199    eglWaitClient();
     200
     201    // Copy srcRect from the backing store to the new pixmap
     202    XSetGraphicsExposures(X11->display, tmpGc, False);
     203    XCopyArea(X11->display, m_backBuffer.handle(), px.handle(), tmpGc,
     204              srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(), 0, 0);
     205    XFreeGC(X11->display, tmpGc);
     206
     207    // Wait until the copy has finised before allowing more rendering into the back buffer
     208    eglWaitNative(EGL_CORE_NATIVE_ENGINE);
     209
     210    return px;
     211}
    146212
    147213QT_END_NAMESPACE
  • trunk/src/opengl/qwindowsurface_x11gl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6969    void setGeometry(const QRect &rect);
    7070    bool scroll(const QRegion &area, int dx, int dy);
     71    QPixmap grabWidget(const QWidget *widget, const QRect& rectangle = QRect()) const;
    7172
    7273private:
    73     GC      m_GC;
     74    GC      m_windowGC;
     75    GC      m_pixmapGC;
    7476    QPixmap m_backBuffer;
    7577    QWidget *m_window;
  • trunk/src/opengl/util/fragmentprograms_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/opengl/util/generator.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    288288    out << "/****************************************************************************\n"
    289289           "**\n"
    290            "** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).\n"
     290           "** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
    291291           "** All rights reserved.\n"
    292292           "** Contact: Nokia Corporation (qt-info@nokia.com)\n"
  • trunk/src/opengl/util/glsl_to_include.sh

    r651 r846  
    22#############################################################################
    33##
    4 ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    55## All rights reserved.
    66## Contact: Nokia Corporation (qt-info@nokia.com)
Note: See TracChangeset for help on using the changeset viewer.