Changeset 561 for trunk/src/opengl


Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
12 deleted
62 edited
24 copied

Legend:

Unmodified
Added
Removed
  • trunk

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

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444#include <private/qbezier_p.h>
    4545
     46QT_BEGIN_NAMESPACE
     47
    4648void QGL2PEXVertexArray::clear()
    4749{
    4850    vertexArray.reset();
    49     vertexArrayStops.clear();
     51    vertexArrayStops.reset();
    5052    boundingRectDirty = true;
    5153}
     
    6062}
    6163
    62 void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale)
     64void QGL2PEXVertexArray::addRect(const QRectF &rect)
     65{
     66    vertexArray << rect.topLeft() << rect.topRight() << rect.bottomRight()
     67                << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
     68}
     69
     70void QGL2PEXVertexArray::addClosingLine(int index)
     71{
     72    if (QPointF(vertexArray.at(index)) != QPointF(vertexArray.last()))
     73        vertexArray.add(vertexArray.at(index));
     74}
     75
     76void QGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
     77{
     78    const QPointF *const points = reinterpret_cast<const QPointF *>(path.points());
     79    const QPainterPath::ElementType *const elements = path.elements();
     80
     81    QPointF sum = points[subPathIndex];
     82    int count = 1;
     83
     84    for (int i = subPathIndex + 1; i < path.elementCount() && (!elements || elements[i] != QPainterPath::MoveToElement); ++i) {
     85        sum += points[i];
     86        ++count;
     87    }
     88
     89    const QPointF centroid = sum / qreal(count);
     90    vertexArray.add(centroid);
     91}
     92
     93void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline)
    6394{
    6495    const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
     
    71102    }
    72103
     104    if (!outline && !path.isConvex())
     105        addCentroid(path, 0);
     106
     107    int lastMoveTo = vertexArray.size();
    73108    vertexArray.add(points[0]); // The first element is always a moveTo
    74109
     
    86121
    87122        for (int i=1; i<path.elementCount(); ++i) {
    88             const QPainterPath::ElementType elementType = elements[i];
    89             switch (elementType) {
     123            switch (elements[i]) {
    90124            case QPainterPath::MoveToElement:
     125                if (!outline)
     126                    addClosingLine(lastMoveTo);
    91127//                qDebug("element[%d] is a MoveToElement", i);
    92                 vertexArrayStops.append(vertexArray.size());
    93                 vertexArray.add(points[i]); // Add the moveTo as a new vertex
     128                vertexArrayStops.add(vertexArray.size());
     129                if (!outline) {
     130                    if (!path.isConvex()) addCentroid(path, i);
     131                    lastMoveTo = vertexArray.size();
     132                }
     133                lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex
    94134                break;
    95135            case QPainterPath::LineToElement:
     
    97137                lineToArray(points[i].x(), points[i].y());
    98138                break;
    99             case QPainterPath::CurveToElement:
    100 //                qDebug("element[%d] is a CurveToElement", i);
    101                 curveToArray(points[i], points[i+1], points[i+2], curveInverseScale);
    102                 i+=2;
    103                 break;
     139            case QPainterPath::CurveToElement: {
     140                QBezier b = QBezier::fromPoints(*(((const QPointF *) points) + i - 1),
     141                                                points[i],
     142                                                points[i+1],
     143                                                points[i+2]);
     144                QRectF bounds = b.bounds();
     145                // threshold based on same algorithm as in qtriangulatingstroker.cpp
     146                int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6));
     147                if (threshold < 3) threshold = 3;
     148                qreal one_over_threshold_minus_1 = 1.f / (threshold - 1);
     149                for (int t=0; t<threshold; ++t) {
     150                    QPointF pt = b.pointAt(t * one_over_threshold_minus_1);
     151                    lineToArray(pt.x(), pt.y());
     152                }
     153                i += 2;
     154                break; }
    104155            default:
    105156                break;
     
    108159    } while (0);
    109160
    110     vertexArrayStops.append(vertexArray.size());
     161    if (!outline)
     162        addClosingLine(lastMoveTo);
     163    vertexArrayStops.add(vertexArray.size());
    111164}
    112165
     
    125178}
    126179
    127 void QGL2PEXVertexArray::curveToArray(const QGLPoint &cp1, const QGLPoint &cp2, const QGLPoint &ep, GLfloat inverseScale)
    128 {
    129     qreal inverseScaleHalf = inverseScale / 2;
    130 
    131     QBezier beziers[32];
    132     beziers[0] = QBezier::fromPoints(vertexArray.last(), cp1, cp2, ep);
    133     QBezier *b = beziers;
    134     while (b >= beziers) {
    135         // check if we can pop the top bezier curve from the stack
    136         qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
    137         qreal d;
    138         if (l > inverseScale) {
    139             d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) )
    140                 + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) );
    141             d /= l;
    142         } else {
    143             d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
    144                 qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
    145         }
    146         if (d < inverseScaleHalf || b == beziers + 31) {
    147             // good enough, we pop it off and add the endpoint
    148             lineToArray(b->x4, b->y4);
    149             --b;
    150         } else {
    151             // split, second half of the polygon goes lower into the stack
    152             b->split(b+1, b);
    153            ++b;
    154         }
    155     }
    156 }
     180QT_END_NAMESPACE
  • trunk/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5151//
    5252
     53#ifndef QGL2PEXVERTEXARRAY_P_H
     54#define QGL2PEXVERTEXARRAY_P_H
     55
    5356#include <QRectF>
    5457
     
    5659#include <private/qvectorpath_p.h>
    5760#include <private/qgl_p.h>
     61
     62QT_BEGIN_NAMESPACE
    5863
    5964class QGLPoint
     
    6368        x(new_x), y(new_y) {};
    6469
    65     QGLPoint(QPointF p) :
     70    QGLPoint(const QPointF &p) :
    6671        x(p.x()), y(p.y()) {};
    6772
     
    7883struct QGLRect
    7984{
    80     QGLRect(QRectF r)
     85    QGLRect(const QRectF &r)
    8186        :  left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
    8287
     
    99104        boundingRectDirty(true) {}
    100105
    101     void addPath(const QVectorPath &path, GLfloat curveInverseScale);
     106    void addRect(const QRectF &rect);
     107    void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
    102108    void clear();
    103109
    104110    QGLPoint*        data() {return vertexArray.data();}
    105     QVector<int>&   stops() {return vertexArrayStops;}
     111    int *stops() const { return vertexArrayStops.data(); }
     112    int stopCount() const { return vertexArrayStops.size(); }
    106113    QGLRect         boundingRect() const;
     114
     115    int vertexCount() const { return vertexArray.size(); }
    107116
    108117    void lineToArray(const GLfloat x, const GLfloat y);
     
    110119private:
    111120    QDataBuffer<QGLPoint> vertexArray;
    112     QVector<int>          vertexArrayStops;
     121    QDataBuffer<int>      vertexArrayStops;
    113122
    114123    GLfloat     maxX;
     
    117126    GLfloat     minY;
    118127    bool        boundingRectDirty;
     128    void addClosingLine(int index);
     129    void addCentroid(const QVectorPath &path, int subPathIndex);
     130};
    119131
    120     inline void curveToArray(const QGLPoint &cp1, const QGLPoint &cp2, const QGLPoint &ep, GLfloat inverseScale);
    121 };
     132QT_END_NAMESPACE
     133
     134#endif
  • trunk/src/opengl/gl2paintengineex/qglgradientcache.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545#include "qglgradientcache_p.h"
    4646
    47 void QGLGradientCache::cleanCache() {
     47QT_BEGIN_NAMESPACE
     48
     49static void QGL2GradientCache_free(void *ptr)
     50{
     51    delete reinterpret_cast<QGL2GradientCache *>(ptr);
     52}
     53
     54Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free))
     55
     56QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context)
     57{
     58    QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context));
     59    if (!p) {
     60        QGLShareContextScope scope(context);
     61        p = new QGL2GradientCache;
     62        qt_gradient_caches()->insert(context, p);
     63    }
     64    return p;
     65}
     66
     67void QGL2GradientCache::cleanCache() {
    4868    QGLGradientColorTableHash::const_iterator it = cache.constBegin();
    4969    for (; it != cache.constEnd(); ++it) {
     
    5474}
    5575
    56 GLuint QGLGradientCache::getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx)
     76GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
    5777{
    58     if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx))
    59         cleanCache();
    60 
    61     buffer_ctx = ctx;
    62 
    6378    quint64 hash_val = 0;
    6479
     
    85100
    86101
    87 GLuint QGLGradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
     102GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
    88103{
    89104    if (cache.size() == maxCacheSize()) {
     
    110125
    111126
    112 // GL's expects pixels in RGBA, bin-endian (ABGR on x86).
    113 // Qt stores in ARGB using whatever byte-order the mancine uses.
     127// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86).
     128// Qt always stores in ARGB reguardless of the byte-order the mancine uses.
    114129static inline uint qtToGlColor(uint c)
    115130{
    116131    uint o;
    117132#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
    118     o = c & 0xFF00FF00; // alpha & green already in the right place
    119     o |= (c >> 16) & 0x000000FF; // red
    120     o |= (c << 16) & 0x00FF0000; // blue
    121 
     133    o = (c & 0xff00ff00)  // alpha & green already in the right place
     134        | ((c >> 16) & 0x000000ff) // red
     135        | ((c << 16) & 0x00ff0000); // blue
    122136#else //Q_BIG_ENDIAN
    123     o = c & 0x00FF00FF; // alpha & green already in the right place
    124     o |= (c << 16) & 0xFF000000; // red
    125     o |= (c >> 16) & 0x0000FF00; // blue
    126 #error big endian not tested with QGLGraphicsContext
     137    o = (c << 8)
     138        | ((c >> 24) & 0x000000ff);
    127139#endif // Q_BYTE_ORDER
    128140    return o;
     
    130142
    131143//TODO: Let GL generate the texture using an FBO
    132 void QGLGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
     144void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
    133145{
    134146    int pos = 0;
     
    137149
    138150    for (int i = 0; i < s.size(); ++i)
    139         colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB
     151        colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
    140152
    141153    bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
     
    184196    colorTable[size-1] = last_color;
    185197}
     198
     199QT_END_NAMESPACE
  • trunk/src/opengl/gl2paintengineex/qglgradientcache_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353#include <QMultiHash>
    5454#include <QObject>
    55 #include <QtOpenGL>
     55#include <QtOpenGL/QtOpenGL>
     56#include <private/qgl_p.h>
    5657
    57 class QGLGradientCache : public QObject
     58QT_BEGIN_NAMESPACE
     59
     60class QGL2GradientCache
    5861{
    59     Q_OBJECT
    6062    struct CacheInfo
    6163    {
     
    7274
    7375public:
    74     QGLGradientCache() : QObject(), buffer_ctx(0)
    75     {
    76 /*
    77         connect(QGLSignalProxy::instance(),
    78                 SIGNAL(aboutToDestroyContext(const QGLContext *)),
    79                 SLOT(cleanupGLContextRefs(const QGLContext *)));
    80 */
    81     }
     76    static QGL2GradientCache *cacheForContext(const QGLContext *context);
    8277
    83     GLuint getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx);
     78    QGL2GradientCache() { }
     79    ~QGL2GradientCache() {cleanCache();}
     80
     81    GLuint getBuffer(const QGradient &gradient, qreal opacity);
    8482    inline int paletteSize() const { return 1024; }
    8583
     
    9492
    9593    QGLGradientColorTableHash cache;
    96     const QGLContext *buffer_ctx;
    97 
    98 public slots:
    99     void cleanupGLContextRefs(const QGLContext *context) {
    100         if (context == buffer_ctx) {
    101             cleanCache();
    102             buffer_ctx = 0;
    103         }
    104     }
    10594};
    10695
     96QT_END_NAMESPACE
    10797
    108 
  • trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6363*/
    6464
     65// #define QT_OPENGL_CACHE_AS_VBOS
    6566
    6667#include "qpaintengineex_opengl2_p.h"
     
    7677#include <private/qfontengine_p.h>
    7778#include <private/qtextureglyphcache_p.h>
     79#include <private/qpixmapdata_gl_p.h>
     80#include <private/qdatabuffer_p.h>
    7881
    7982#include "qglgradientcache_p.h"
    80 #include "qglpexshadermanager_p.h"
     83#include "qglengineshadermanager_p.h"
    8184#include "qgl2pexvertexarray_p.h"
    8285
    83 
    84 extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
    85 
     86#include "qtriangulatingstroker_p.h"
    8687
    8788#include <QDebug>
    8889
    89 
    90 static const GLuint QT_VERTEX_COORDS_ATTR  = 0;
    91 static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
    92 static const GLuint QT_BRUSH_TEXTURE_UNIT  = 0;
    93 
    94 class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
    95 {
    96     Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
     90QT_BEGIN_NAMESPACE
     91
     92//#define QT_GL_NO_SCISSOR_TEST
     93
     94static const GLuint GL_STENCIL_HIGH_BIT         = 0x80;
     95static const GLuint QT_BRUSH_TEXTURE_UNIT       = 0;
     96static const GLuint QT_IMAGE_TEXTURE_UNIT       = 0; //Can be the same as brush texture unit
     97static const GLuint QT_MASK_TEXTURE_UNIT        = 1;
     98static const GLuint QT_BACKGROUND_TEXTURE_UNIT  = 2;
     99
     100#ifdef Q_WS_WIN
     101extern Q_GUI_EXPORT bool qt_cleartype_enabled;
     102#endif
     103
     104class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache
     105{
     106    Q_OBJECT
    97107public:
    98     QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
    99             q(q_ptr),
    100             width(0), height(0),
    101             ctx(0),
    102             currentBrush( &(q->state()->brush) ),
    103             inverseScale(1),
    104             shaderManager(0)
    105     { }
    106 
    107     ~QGL2PaintEngineExPrivate();
    108 
    109     void updateBrushTexture();
    110     void updateBrushUniforms();
    111     void updateMatrix();
    112     void updateCompositionMode();
    113     void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform);
    114 
    115     void setBrush(const QBrush* brush);
    116 
    117     void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight);
    118 
    119     void fill(const QVectorPath &path);
    120     void drawOutline(const QVectorPath& path);
    121 
    122     void drawVertexArrays(QGL2PEXVertexArray& vertexArray, GLenum primitive);
    123         // ^ draws whatever is in the vertex array
    124     void composite(const QGLRect& boundingRect);
    125         // ^ Composites the bounding rect onto dest buffer
    126     void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill);
    127         // ^ Calls drawVertexArrays to render into stencil buffer
    128     void cleanStencilBuffer(const QGLRect& area);
    129 
    130     void prepareForDraw();
    131 
    132     inline void useSimpleShader();
    133     inline QColor premultiplyColor(QColor c, GLfloat opacity);
    134 
    135     QGL2PaintEngineEx* q;
    136 
    137     //### Move into QGLDrawable
    138     int width, height;
    139     QGLContext* ctx;
    140 
    141     // Dirty flags
    142     bool matrixDirty; // Implies matrix uniforms are also dirty
    143     bool compositionModeDirty;
    144     bool brushTextureDirty;
    145     bool brushUniformsDirty;
    146     bool simpleShaderMatrixUniformDirty;
    147     bool brushShaderMatrixUniformDirty;
    148     bool imageShaderMatrixUniformDirty;
    149     bool textShaderMatrixUniformDirty;
    150     bool stencilBuferDirty;
    151 
    152     const QBrush*    currentBrush; // May not be the state's brush!
    153 
    154     GLfloat     inverseScale;
    155 
    156     QGL2PEXVertexArray pathVertexArray;
    157 
    158     GLfloat pmvMatrix[4][4];
    159 
    160     QGLPEXShaderManager* shaderManager;
    161 
    162     // Clipping & state stuff stolen from QOpenGLPaintEngine:
    163     void updateDepthClip();
    164     uint use_system_clip : 1;
     108    QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix);
     109    ~QGLTextureGlyphCache();
     110
     111    virtual void createTextureData(int width, int height);
     112    virtual void resizeTextureData(int width, int height);
     113    virtual void fillTexture(const Coord &c, glyph_t glyph);
     114    virtual int glyphMargin() const;
     115
     116    inline GLuint texture() const { return m_texture; }
     117
     118    inline int width() const { return m_width; }
     119    inline int height() const { return m_height; }
     120
     121    inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
     122
     123
     124public Q_SLOTS:
     125    void contextDestroyed(const QGLContext *context) {
     126        if (context == ctx) {
     127            QList<const QGLContext *> shares = qgl_share_reg()->shares(ctx);
     128            if (shares.isEmpty()) {
     129                glDeleteFramebuffers(1, &m_fbo);
     130                if (m_width || m_height)
     131                    glDeleteTextures(1, &m_texture);
     132                ctx = 0;
     133            } else {
     134                // since the context holding the texture is shared, and
     135                // about to be destroyed, we have to transfer ownership
     136                // of the texture to one of the share contexts
     137                ctx = const_cast<QGLContext *>((ctx == shares.at(0)) ? shares.at(1) : shares.at(0));
     138            }
     139        }
     140    }
     141
     142private:
     143    QGLContext *ctx;
     144
     145    QGL2PaintEngineExPrivate *pex;
     146
     147    GLuint m_texture;
     148    GLuint m_fbo;
     149
     150    int m_width;
     151    int m_height;
     152
     153    QGLShaderProgram *m_program;
    165154};
    166155
     156QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
     157    : QTextureGlyphCache(type, matrix)
     158    , ctx(context)
     159    , m_width(0)
     160    , m_height(0)
     161{
     162    glGenFramebuffers(1, &m_fbo);
     163    connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
     164            SLOT(contextDestroyed(const QGLContext*)));
     165}
     166
     167QGLTextureGlyphCache::~QGLTextureGlyphCache()
     168{
     169    if (ctx) {
     170        QGLShareContextScope scope(ctx);
     171        glDeleteFramebuffers(1, &m_fbo);
     172
     173        if (m_width || m_height)
     174            glDeleteTextures(1, &m_texture);
     175    }
     176}
     177
     178void QGLTextureGlyphCache::createTextureData(int width, int height)
     179{
     180    glGenTextures(1, &m_texture);
     181    glBindTexture(GL_TEXTURE_2D, m_texture);
     182
     183    m_width = width;
     184    m_height = height;
     185
     186    QVarLengthArray<uchar> data(width * height);
     187    for (int i = 0; i < data.size(); ++i)
     188        data[i] = 0;
     189
     190    if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
     191        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
     192    else
     193        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
     194
     195    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     196    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     197}
     198
     199void QGLTextureGlyphCache::resizeTextureData(int width, int height)
     200{
     201    // ### the QTextureGlyphCache API needs to be reworked to allow
     202    // ### resizeTextureData to fail
     203
     204    int oldWidth = m_width;
     205    int oldHeight = m_height;
     206
     207    GLuint oldTexture = m_texture;
     208    createTextureData(width, height);
     209
     210    glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
     211
     212    GLuint tmp_texture;
     213    glGenTextures(1, &tmp_texture);
     214    glBindTexture(GL_TEXTURE_2D, tmp_texture);
     215    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
     216                 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
     217    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     218    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     219    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     220    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     221    glBindTexture(GL_TEXTURE_2D, 0);
     222    glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     223                           GL_TEXTURE_2D, tmp_texture, 0);
     224
     225    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     226    glBindTexture(GL_TEXTURE_2D, oldTexture);
     227
     228    pex->transferMode(BrushDrawingMode);
     229
     230    glDisable(GL_STENCIL_TEST);
     231    glDisable(GL_DEPTH_TEST);
     232    glDisable(GL_SCISSOR_TEST);
     233    glDisable(GL_BLEND);
     234
     235    glViewport(0, 0, oldWidth, oldHeight);
     236
     237    float vertexCoordinateArray[] = { -1, -1, 1, -1, 1, 1, -1, 1 };
     238    float textureCoordinateArray[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
     239
     240    glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     241    glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     242
     243    glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray);
     244    glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray);
     245
     246    pex->shaderManager->blitProgram()->bind();
     247    pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
     248    pex->shaderManager->setDirty();
     249
     250    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     251
     252    glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     253    glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     254
     255    glBindTexture(GL_TEXTURE_2D, m_texture);
     256
     257#ifdef QT_OPENGL_ES_2
     258    QDataBuffer<uchar> buffer(4*oldWidth*oldHeight);
     259    buffer.resize(4*oldWidth*oldHeight);
     260    glReadPixels(0, 0, oldWidth, oldHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
     261
     262    // do an in-place conversion from GL_RGBA to GL_ALPHA
     263    for (int i=0; i<oldWidth*oldHeight; ++i)
     264        buffer.data()[i] = buffer.at(4*i + 3);
     265
     266    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight,
     267                    GL_ALPHA, GL_UNSIGNED_BYTE, buffer.data());
     268#else
     269    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
     270#endif
     271
     272    glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     273                              GL_RENDERBUFFER_EXT, 0);
     274    glDeleteTextures(1, &tmp_texture);
     275    glDeleteTextures(1, &oldTexture);
     276
     277    glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
     278
     279    glViewport(0, 0, pex->width, pex->height);
     280    pex->updateClipScissorTest();
     281}
     282
     283void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
     284{
     285    QImage mask = textureMapForGlyph(glyph);
     286    const int maskWidth = mask.width();
     287    const int maskHeight = mask.height();
     288
     289    if (mask.format() == QImage::Format_Mono) {
     290        mask = mask.convertToFormat(QImage::Format_Indexed8);
     291        for (int y = 0; y < maskHeight; ++y) {
     292            uchar *src = (uchar *) mask.scanLine(y);
     293            for (int x = 0; x < maskWidth; ++x)
     294                src[x] = -src[x]; // convert 0 and 1 into 0 and 255
     295        }
     296     }
     297
     298
     299    glBindTexture(GL_TEXTURE_2D, m_texture);
     300    if (mask.format() == QImage::Format_RGB32) {
     301        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
     302    } else {
     303#ifdef QT_OPENGL_ES2
     304        glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
     305#else
     306        // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
     307        // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
     308        // and nVidia GeForce 8500GT. GL_UNPACK_ALIGNMENT is set to four bytes, 'mask' has a
     309        // multiple of four bytes per line, and most of the glyph shows up correctly in the
     310        // texture, which makes me think that this is a driver bug.
     311        // One workaround is to make sure the mask width is a multiple of four bytes, for instance
     312        // by converting it to a format with four bytes per pixel. Another is to copy one line at a
     313        // time.
     314
     315        for (int i = 0; i < maskHeight; ++i)
     316            glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
     317#endif
     318    }
     319}
     320
     321int QGLTextureGlyphCache::glyphMargin() const
     322{
     323#if defined(Q_WS_MAC)
     324    return 2;
     325#elif defined (Q_WS_X11)
     326    return 0;
     327#else
     328    return m_type == QFontEngineGlyphCache::Raster_RGBMask ? 2 : 0;
     329#endif
     330}
     331
     332extern QImage qt_imageForBrush(int brushStyle, bool invert);
    167333
    168334////////////////////////////////// Private Methods //////////////////////////////////////////
     
    170336QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
    171337{
    172     if (shaderManager) {
    173         delete shaderManager;
    174         shaderManager = 0;
    175     }
    176 }
    177 
    178 void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform)
    179 {
    180     glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
     338    delete shaderManager;
     339
     340    while (pathCaches.size()) {
     341        QVectorPath::CacheEntry *e = *(pathCaches.constBegin());
     342        e->cleanup(e->engine, e->data);
     343        e->data = 0;
     344        e->engine = 0;
     345    }
     346}
     347
     348void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
     349{
     350//    glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
     351    if (id != GLuint(-1) && id == lastTextureUsed)
     352        return;
     353
     354    lastTextureUsed = id;
    181355
    182356    if (smoothPixmapTransform) {
     
    192366
    193367
    194 QColor QGL2PaintEngineExPrivate::premultiplyColor(QColor c, GLfloat opacity)
    195 {
    196     uint alpha = qRound(c.alpha() * opacity);
    197     return QColor ( ((c.red() * alpha + 128) >> 8),
    198                     ((c.green() * alpha + 128) >> 8),
    199                     ((c.blue() * alpha + 128) >> 8),
    200                     alpha);
    201 }
    202 
    203 
    204 void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush)
    205 {
     368inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
     369{
     370    qreal alpha = c.alphaF() * opacity;
     371    c.setAlphaF(alpha);
     372    c.setRedF(c.redF() * alpha);
     373    c.setGreenF(c.greenF() * alpha);
     374    c.setBlueF(c.blueF() * alpha);
     375    return c;
     376}
     377
     378
     379void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
     380{
     381    if (qbrush_fast_equals(currentBrush, brush))
     382        return;
     383
     384    const Qt::BrushStyle newStyle = qbrush_style(brush);
     385    Q_ASSERT(newStyle != Qt::NoBrush);
     386
    206387    currentBrush = brush;
    207     brushTextureDirty = true;
    208     brushUniformsDirty = true;
    209     shaderManager->setBrushStyle(currentBrush->style());
    210     shaderManager->setAffineOnlyBrushTransform(currentBrush->transform().isAffine());
    211 }
    212 
    213 
    214 // Unless this gets used elsewhere, it's probably best to merge it into fillStencilWithVertexArray
     388    brushUniformsDirty = true; // All brushes have at least one uniform
     389
     390    if (newStyle > Qt::SolidPattern)
     391        brushTextureDirty = true;
     392
     393    if (currentBrush.style() == Qt::TexturePattern
     394        && qHasPixmapTexture(brush) && brush.texture().isQBitmap())
     395    {
     396        shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
     397    } else {
     398        shaderManager->setSrcPixelType(newStyle);
     399    }
     400    shaderManager->optimiseForBrushTransform(currentBrush.transform().type());
     401}
     402
     403
    215404void QGL2PaintEngineExPrivate::useSimpleShader()
    216405{
    217     shaderManager->simpleShader()->use();
     406    shaderManager->simpleProgram()->bind();
     407    shaderManager->setDirty();
    218408
    219409    if (matrixDirty)
     
    221411
    222412    if (simpleShaderMatrixUniformDirty) {
    223         shaderManager->simpleShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
     413        const GLuint location = shaderManager->simpleProgram()->uniformLocation("pmvMatrix");
     414        glUniformMatrix3fv(location, 1, GL_FALSE, (GLfloat*)pmvMatrix);
    224415        simpleShaderMatrixUniformDirty = false;
    225416    }
    226417}
    227418
    228 
    229 Q_GLOBAL_STATIC(QGLGradientCache, qt_opengl_gradient_cache)
    230 
    231419void QGL2PaintEngineExPrivate::updateBrushTexture()
    232420{
     421    Q_Q(QGL2PaintEngineEx);
    233422//     qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()");
    234     Qt::BrushStyle style = currentBrush->style();
     423    Qt::BrushStyle style = currentBrush.style();
    235424
    236425    if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
    237426        // Get the image data for the pattern
    238         QImage texImage = qt_imageForBrush(style, true);
    239 
    240         glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
    241         ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true);
    242         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
     427        QImage texImage = qt_imageForBrush(style, false);
     428
     429        glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
     430        ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true, QGLContext::InternalBindOption);
     431        updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
    243432    }
    244433    else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
    245434        // Gradiant brush: All the gradiants use the same texture
    246435
    247         const QGradient* g = currentBrush->gradient();
     436        const QGradient* g = currentBrush.gradient();
    248437
    249438        // We apply global opacity in the fragment shaders, so we always pass 1.0
    250439        // for opacity to the cache.
    251         GLuint texId = qt_opengl_gradient_cache()->getBuffer(*g, 1.0, ctx);
     440        GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0);
     441
     442        glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
     443        glBindTexture(GL_TEXTURE_2D, texId);
    252444
    253445        if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient)
    254             updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
     446            updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
    255447        else if (g->spread() == QGradient::ReflectSpread)
    256             updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, true);
     448            updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, q->state()->renderHints & QPainter::SmoothPixmapTransform);
    257449        else
    258             updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true);
    259 
    260         glBindTexture(GL_TEXTURE_2D, texId);
     450            updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform);
    261451    }
    262452    else if (style == Qt::TexturePattern) {
    263         const QPixmap& texPixmap = currentBrush->texture();
    264 
    265         glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
    266         ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, true);
    267         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
     453        const QPixmap& texPixmap = currentBrush.texture();
     454
     455        glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
     456        QGLTexture *tex = ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
     457        updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
     458        textureInvertedY = tex->options & QGLContext::InvertedYBindOption ? -1 : 1;
    268459    }
    269460    brushTextureDirty = false;
     
    274465{
    275466//     qDebug("QGL2PaintEngineExPrivate::updateBrushUniforms()");
    276     Qt::BrushStyle style = currentBrush->style();
     467    Qt::BrushStyle style = currentBrush.style();
    277468
    278469    if (style == Qt::NoBrush)
    279470        return;
    280471
    281     GLfloat opacity = 1.0;
    282     if (q->state()->opacity < 0.99f)
    283         opacity = (GLfloat)q->state()->opacity;
    284     bool setOpacity = true;
    285 
    286     QTransform brushQTransform = currentBrush->transform();
     472    QTransform brushQTransform = currentBrush.transform();
    287473
    288474    if (style == Qt::SolidPattern) {
    289         QColor col = premultiplyColor(currentBrush->color(), opacity);
    290         shaderManager->brushShader()->uniforms()[QLatin1String("fragmentColor")] = col;
    291         setOpacity = false;
     475        QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
     476        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col);
    292477    }
    293478    else {
     
    296481
    297482        if (style <= Qt::DiagCrossPattern) {
    298             translationPoint = q->state()->brushOrigin;
    299 
    300             QColor col = premultiplyColor(currentBrush->color(), opacity);
    301 
    302             shaderManager->brushShader()->uniforms()[QLatin1String("patternColor")] = col;
    303             setOpacity = false; //So code below doesn't try to set the opacity uniform
    304 
    305             QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
    306             shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
     483            QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
     484
     485            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
     486
     487            QVector2D halfViewportSize(width*0.5, height*0.5);
     488            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
    307489        }
    308490        else if (style == Qt::LinearGradientPattern) {
    309             const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient());
     491            const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient());
    310492
    311493            QPointF realStart = g->start();
     
    315497            QPointF l = realFinal - realStart;
    316498
    317             // ###
    318             QGLVec3 linearData = {
     499            QVector3D linearData(
    319500                l.x(),
    320501                l.y(),
    321502                1.0f / (l.x() * l.x() + l.y() * l.y())
    322             };
    323 
    324             shaderManager->brushShader()->uniforms()[QLatin1String("linearData")] = linearData;
    325 
    326             QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
    327             shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
     503            );
     504
     505            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::LinearData), linearData);
     506
     507            QVector2D halfViewportSize(width*0.5, height*0.5);
     508            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
    328509        }
    329510        else if (style == Qt::ConicalGradientPattern) {
    330             const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient());
     511            const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient());
    331512            translationPoint   = g->center();
    332513
    333514            GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0;
    334515
    335             shaderManager->brushShader()->uniforms()[QLatin1String("angle")] = angle;
    336 
    337             QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
    338             shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
     516            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Angle), angle);
     517
     518            QVector2D halfViewportSize(width*0.5, height*0.5);
     519            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
    339520        }
    340521        else if (style == Qt::RadialGradientPattern) {
    341             const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient());
     522            const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient());
    342523            QPointF realCenter = g->center();
    343524            QPointF realFocal  = g->focalPoint();
     
    346527
    347528            QPointF fmp = realCenter - realFocal;
    348             shaderManager->brushShader()->uniforms()[QLatin1String("fmp")] = fmp;
     529            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp), fmp);
    349530
    350531            GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
    351             shaderManager->brushShader()->uniforms()[QLatin1String("fmp2_m_radius2")] = fmp2_m_radius2;
    352 
    353             shaderManager->brushShader()->uniforms()[QLatin1String("inverse_2_fmp2_m_radius2")] =
    354                                                         GLfloat(1.0 / (2.0*fmp2_m_radius2));
    355 
    356             QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
    357             shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
     532            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
     533            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2),
     534                                                             GLfloat(1.0 / (2.0*fmp2_m_radius2)));
     535
     536            QVector2D halfViewportSize(width*0.5, height*0.5);
     537            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
    358538        }
    359539        else if (style == Qt::TexturePattern) {
    360             translationPoint = q->state()->brushOrigin;
    361 
    362             const QPixmap& texPixmap = currentBrush->texture();
    363 
    364             QSizeF invertedTextureSize( 1.0 / texPixmap.width(), 1.0 / texPixmap.height() );
    365             shaderManager->brushShader()->uniforms()[QLatin1String("invertedTextureSize")] = invertedTextureSize;
    366 
    367             QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
    368             shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
     540            const QPixmap& texPixmap = currentBrush.texture();
     541
     542            if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) {
     543                QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
     544                shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
     545            }
     546
     547            QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 / texPixmap.height());
     548            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::InvertedTextureSize), invertedTextureSize);
     549
     550            QVector2D halfViewportSize(width*0.5, height*0.5);
     551            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
    369552        }
    370553        else
    371554            qWarning("QGL2PaintEngineEx: Unimplemented fill style");
    372555
     556        const QPointF &brushOrigin = q->state()->brushOrigin;
     557        QTransform matrix = q->state()->matrix;
     558        matrix.translate(brushOrigin.x(), brushOrigin.y());
     559
    373560        QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y());
    374561        QTransform gl_to_qt(1, 0, 0, -1, 0, height);
    375         QTransform inv_matrix = gl_to_qt * (brushQTransform * q->state()->matrix).inverted() * translate;
    376 
    377         shaderManager->brushShader()->uniforms()[QLatin1String("brushTransform")] = inv_matrix;
    378         shaderManager->brushShader()->uniforms()[QLatin1String("brushTexture")] = QT_BRUSH_TEXTURE_UNIT;
    379 
    380         if (setOpacity)
    381             shaderManager->brushShader()->uniforms()[QLatin1String("opacity")] = opacity;
     562        QTransform inv_matrix;
     563        if (style == Qt::TexturePattern && textureInvertedY == -1)
     564            inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate;
     565        else
     566            inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate;
     567
     568        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTransform), inv_matrix);
     569        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT);
    382570    }
    383571    brushUniformsDirty = false;
     
    390578//     qDebug("QGL2PaintEngineExPrivate::updateMatrix()");
    391579
    392     // We setup the Projection matrix to be the equivilant of glOrtho(0, w, h, 0, -1, 1):
    393     GLfloat P[4][4] = {
    394         {2.0/width,  0.0,        0.0, -1.0},
    395         {0.0,       -2.0/height, 0.0,  1.0},
    396         {0.0,        0.0,       -1.0,  0.0},
    397         {0.0,        0.0,        0.0,  1.0}
    398     };
    399 
    400     // Use the (3x3) transform for the Model~View matrix:
    401580    const QTransform& transform = q->state()->matrix;
    402     GLfloat MV[4][4] = {
    403         {transform.m11(), transform.m21(), 0.0, transform.dx() + 0.5},
    404         {transform.m12(), transform.m22(), 0.0, transform.dy() + 0.5},
    405         {0.0,             0.0,             1.0, 0.0},
    406         {transform.m13(), transform.m23(), 0.0, transform.m33()}
    407     };
    408 
    409     // NOTE: OpenGL ES works with column-major matrices, so when we multiply the matrices,
    410     //       we also transpose them ready for GL.
    411     for (int row = 0; row < 4; ++row) {
    412         for (int col = 0; col < 4; ++col) {
    413             pmvMatrix[col][row] = 0.0;
    414             for (int n = 0; n < 4; ++n)
    415                 pmvMatrix[col][row] += P[row][n] * MV[n][col];
    416         }
    417     }
     581
     582    // The projection matrix converts from Qt's coordinate system to GL's coordinate system
     583    //    * GL's viewport is 2x2, Qt's is width x height
     584    //    * GL has +y -> -y going from bottom -> top, Qt is the other way round
     585    //    * GL has [0,0] in the center, Qt has it in the top-left
     586    //
     587    // This results in the Projection matrix below, which is multiplied by the painter's
     588    // transformation matrix, as shown below:
     589    //
     590    //                Projection Matrix                      Painter Transform
     591    // ------------------------------------------------   ------------------------
     592    // | 2.0 / width  |      0.0      |     -1.0      |   |  m11  |  m21  |  dx  |
     593    // |     0.0      | -2.0 / height |      1.0      | * |  m12  |  m22  |  dy  |
     594    // |     0.0      |      0.0      |      1.0      |   |  m13  |  m23  |  m33 |
     595    // ------------------------------------------------   ------------------------
     596    //
     597    // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies
     598
     599    const GLfloat wfactor = 2.0f / width;
     600    const GLfloat hfactor = -2.0f / height;
     601    GLfloat dx = transform.dx();
     602    GLfloat dy = transform.dy();
     603
     604    // Non-integer translates can have strange effects for some rendering operations such as
     605    // anti-aliased text rendering. In such cases, we snap the translate to the pixel grid.
     606    if (snapToPixelGrid && transform.type() == QTransform::TxTranslate) {
     607        // 0.50 needs to rounded down to 0.0 for consistency with raster engine:
     608        dx = ceilf(dx - 0.5f);
     609        dy = ceilf(dy - 0.5f);
     610    }
     611
     612    if (addOffset) {
     613        dx += 0.49f;
     614        dy += 0.49f;
     615    }
     616
     617    pmvMatrix[0][0] = (wfactor * transform.m11())  - transform.m13();
     618    pmvMatrix[1][0] = (wfactor * transform.m21())  - transform.m23();
     619    pmvMatrix[2][0] = (wfactor * dx) - transform.m33();
     620    pmvMatrix[0][1] = (hfactor * transform.m12())  + transform.m13();
     621    pmvMatrix[1][1] = (hfactor * transform.m22())  + transform.m23();
     622    pmvMatrix[2][1] = (hfactor * dy) + transform.m33();
     623    pmvMatrix[0][2] = transform.m13();
     624    pmvMatrix[1][2] = transform.m23();
     625    pmvMatrix[2][2] = transform.m33();
    418626
    419627    // 1/10000 == 0.0001, so we have good enough res to cover curves
     
    427635    // The actual data has been updated so both shader program's uniforms need updating
    428636    simpleShaderMatrixUniformDirty = true;
    429     brushShaderMatrixUniformDirty = true;
    430     imageShaderMatrixUniformDirty = true;
    431     textShaderMatrixUniformDirty = true;
     637    shaderMatrixUniformDirty = true;
     638
     639    dasher.setInvScale(inverseScale);
     640    stroker.setInvScale(inverseScale);
    432641}
    433642
     
    486695}
    487696
    488 
    489 void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight)
    490 {
    491 //     qDebug("QGL2PaintEngineExPrivate::drawImage()");
    492 
    493     // We have a shader specifically for drawPixmap/drawImage...
    494     shaderManager->imageShader()->use();
    495 
    496     updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
    497 
    498     if (compositionModeDirty)
    499         updateCompositionMode();
    500 
     697static inline void setCoords(GLfloat *coords, const QGLRect &rect)
     698{
     699    coords[0] = rect.left;
     700    coords[1] = rect.top;
     701    coords[2] = rect.right;
     702    coords[3] = rect.top;
     703    coords[4] = rect.right;
     704    coords[5] = rect.bottom;
     705    coords[6] = rect.left;
     706    coords[7] = rect.bottom;
     707}
     708
     709void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
     710{
     711    // Setup for texture drawing
     712    currentBrush = noBrush;
     713    shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
     714
     715    if (addOffset) {
     716        addOffset = false;
     717        matrixDirty = true;
     718    }
     719
     720    if (snapToPixelGrid) {
     721        snapToPixelGrid = false;
     722        matrixDirty = true;
     723    }
     724
     725    if (prepareForDraw(opaque))
     726        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
     727
     728    if (pattern) {
     729        QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
     730        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
     731    }
     732
     733    GLfloat dx = 1.0 / textureSize.width();
     734    GLfloat dy = 1.0 / textureSize.height();
     735
     736    QGLRect srcTextureRect(src.left*dx, src.top*dy, src.right*dx, src.bottom*dy);
     737
     738    setCoords(staticVertexCoordinateArray, dest);
     739    setCoords(staticTextureCoordinateArray, srcTextureRect);
     740
     741    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     742}
     743
     744void QGL2PaintEngineEx::beginNativePainting()
     745{
     746    Q_D(QGL2PaintEngineEx);
     747    ensureActive();
     748    d->transferMode(BrushDrawingMode);
     749
     750    QGLContext *ctx = d->ctx;
     751    glUseProgram(0);
     752
     753#ifndef QT_OPENGL_ES_2
     754    // be nice to people who mix OpenGL 1.x code with QPainter commands
     755    // by setting modelview and projection matrices to mirror the GL 1
     756    // paint engine
     757    const QTransform& mtx = state()->matrix;
     758
     759    float mv_matrix[4][4] =
     760    {
     761        { mtx.m11(), mtx.m12(),     0, mtx.m13() },
     762        { mtx.m21(), mtx.m22(),     0, mtx.m23() },
     763        {         0,         0,     1,         0 },
     764        {  mtx.dx(),  mtx.dy(),     0, mtx.m33() }
     765    };
     766
     767    const QSize sz = d->device->size();
     768
     769    glMatrixMode(GL_PROJECTION);
     770    glLoadIdentity();
     771    glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
     772
     773    glMatrixMode(GL_MODELVIEW);
     774    glLoadMatrixf(&mv_matrix[0][0]);
     775#else
     776    Q_UNUSED(ctx);
     777#endif
     778
     779    d->lastTextureUsed = GLuint(-1);
     780    d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
     781    d->resetGLState();
     782
     783    d->shaderManager->setDirty();
     784
     785    d->needsSync = true;
     786}
     787
     788void QGL2PaintEngineExPrivate::resetGLState()
     789{
     790    glDisable(GL_BLEND);
     791    glActiveTexture(GL_TEXTURE0);
     792    glDisable(GL_STENCIL_TEST);
     793    glDisable(GL_DEPTH_TEST);
     794    glDisable(GL_SCISSOR_TEST);
     795    glDepthMask(true);
     796    glDepthFunc(GL_LESS);
     797    glClearDepth(1);
     798}
     799
     800void QGL2PaintEngineEx::endNativePainting()
     801{
     802    Q_D(QGL2PaintEngineEx);
     803    d->needsSync = true;
     804}
     805
     806void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
     807{
     808    if (newMode == mode)
     809        return;
     810
     811    if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) {
     812        glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     813        glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     814        glDisableVertexAttribArray(QT_OPACITY_ATTR);
     815
     816        lastTextureUsed = GLuint(-1);
     817    }
     818
     819    if (newMode == TextDrawingMode) {
     820        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     821        glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     822
     823        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
     824        glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
     825    }
     826
     827    if (newMode == ImageDrawingMode) {
     828        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     829        glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     830
     831        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticVertexCoordinateArray);
     832        glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
     833    }
     834
     835    if (newMode == ImageArrayDrawingMode) {
     836        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     837        glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     838        glEnableVertexAttribArray(QT_OPACITY_ATTR);
     839
     840        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
     841        glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
     842        glVertexAttribPointer(QT_OPACITY_ATTR, 1, GL_FLOAT, GL_FALSE, 0, opacityArray.data());
     843    }
     844
     845    // This needs to change when we implement high-quality anti-aliasing...
     846    if (newMode != TextDrawingMode)
     847        shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
     848
     849    mode = newMode;
     850}
     851
     852struct QGL2PEVectorPathCache
     853{
     854#ifdef QT_OPENGL_CACHE_AS_VBOS
     855    GLuint vbo;
     856#else
     857    float *vertices;
     858#endif
     859    int vertexCount;
     860    GLenum primitiveType;
     861    qreal iscale;
     862};
     863
     864void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data)
     865{
     866    QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data;
     867#ifdef QT_OPENGL_CACHE_AS_VBOS
     868    Q_ASSERT(engine->type() == QPaintEngine::OpenGL2);
     869    static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo;
     870#else
     871    Q_UNUSED(engine);
     872    qFree(c->vertices);
     873#endif
     874    delete c;
     875}
     876
     877// Assumes everything is configured for the brush you want to use
     878void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
     879{
     880    transferMode(BrushDrawingMode);
     881
     882    const QOpenGL2PaintEngineState *s = q->state();
     883    const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) &&
     884                              (qbrush_style(currentBrush) == Qt::SolidPattern) &&
     885                              !multisamplingAlwaysEnabled;
     886
     887    if (addOffset != newAddOffset) {
     888        addOffset = newAddOffset;
     889        matrixDirty = true;
     890    }
     891
     892    if (snapToPixelGrid) {
     893        snapToPixelGrid = false;
     894        matrixDirty = true;
     895    }
     896
     897    // Might need to call updateMatrix to re-calculate inverseScale
    501898    if (matrixDirty)
    502899        updateMatrix();
    503900
    504     if (imageShaderMatrixUniformDirty) {
    505         shaderManager->imageShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
    506         imageShaderMatrixUniformDirty = false;
    507     }
    508 
    509     shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
    510 
    511 //    if (q->state()->opacity < 0.99f)
    512         shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)q->state()->opacity;
    513 
    514     GLfloat vertexCoords[] = {
    515         dest.left,  dest.top,
    516         dest.left,  dest.bottom,
    517         dest.right, dest.bottom,
    518         dest.right, dest.top
    519     };
    520 
    521     glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    522     glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
    523 
    524     GLfloat dx = 1.0 / txtWidth;
    525     GLfloat dy = 1.0 / txtHeight;
    526 
    527     QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
    528 
    529     GLfloat textureCoords[] = {
    530         srcTextureRect.left,  srcTextureRect.top,
    531         srcTextureRect.left,  srcTextureRect.bottom,
    532         srcTextureRect.right, srcTextureRect.bottom,
    533         srcTextureRect.right, srcTextureRect.top
    534     };
    535 
    536     glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
    537     glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
    538 
    539     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    540 
    541     glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
    542     glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    543 }
    544 
    545 
    546 void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
    547 {
    548 //     qDebug("QGL2PaintEngineExPrivate::drawOutline()");
    549     if (matrixDirty)
    550         updateMatrix();
    551 
    552     pathVertexArray.clear();
    553     pathVertexArray.addPath(path, inverseScale);
    554 
    555     if (path.hasImplicitClose()) {
    556         // Close the path's outline
    557         pathVertexArray.lineToArray(path.points()[0], path.points()[1]);
    558         pathVertexArray.stops().last() += 1;
    559     }
    560 
    561     prepareForDraw();
    562     drawVertexArrays(pathVertexArray, GL_LINE_STRIP);
    563 }
    564 
    565 
    566 // Assumes everything is configured for the brush you want to use
    567 void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
    568 {
    569     if (matrixDirty)
    570         updateMatrix();
    571 
    572901    const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
    573 
    574902
    575903    // Check to see if there's any hints
    576904    if (path.shape() == QVectorPath::RectangleHint) {
    577905        QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
    578         prepareForDraw();
     906        prepareForDraw(currentBrush.isOpaque());
    579907        composite(rect);
    580     }
    581     else if (path.shape() == QVectorPath::EllipseHint) {
    582         pathVertexArray.clear();
    583         pathVertexArray.addPath(path, inverseScale);
    584         prepareForDraw();
    585         drawVertexArrays(pathVertexArray, GL_TRIANGLE_FAN);
    586     }
    587     else {
     908    } else if (path.isConvex()) {
     909
     910        if (path.isCacheable()) {
     911            QVectorPath::CacheEntry *data = path.lookupCacheData(q);
     912            QGL2PEVectorPathCache *cache;
     913
     914            if (data) {
     915                cache = (QGL2PEVectorPathCache *) data->data;
     916                // Check if scale factor is exceeded for curved paths and generate curves if so...
     917                if (path.isCurved()) {
     918                    qreal scaleFactor = cache->iscale / inverseScale;
     919                    if (scaleFactor < 0.5 || scaleFactor > 2.0) {
     920#ifdef QT_OPENGL_CACHE_AS_VBOS
     921                        glDeleteBuffers(1, &cache->vbo);
     922                        cache->vbo = 0;
     923#else
     924                        qFree(cache->vertices);
     925#endif
     926                        cache->vertexCount = 0;
     927                    }
     928                }
     929            } else {
     930                cache = new QGL2PEVectorPathCache;
     931                cache->vertexCount = 0;
     932                data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath);
     933            }
     934
     935            // Flatten the path at the current scale factor and fill it into the cache struct.
     936            if (!cache->vertexCount) {
     937                vertexCoordinateArray.clear();
     938                vertexCoordinateArray.addPath(path, inverseScale, false);
     939                int vertexCount = vertexCoordinateArray.vertexCount();
     940                int floatSizeInBytes = vertexCount * 2 * sizeof(float);
     941                cache->vertexCount = vertexCount;
     942                cache->primitiveType = GL_TRIANGLE_FAN;
     943                cache->iscale = inverseScale;
     944#ifdef QT_OPENGL_CACHE_AS_VBOS
     945                glGenBuffers(1, &cache->vbo);
     946                glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
     947                glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
     948#else
     949                cache->vertices = (float *) qMalloc(floatSizeInBytes);
     950                memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes);
     951#endif
     952            }
     953
     954            prepareForDraw(currentBrush.isOpaque());
     955            glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     956#ifdef QT_OPENGL_CACHE_AS_VBOS
     957            glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
     958            glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, 0);
     959#else
     960            glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, cache->vertices);
     961#endif
     962            glDrawArrays(cache->primitiveType, 0, cache->vertexCount);
     963
     964        } else {
     965      //        printf(" - Marking path as cachable...\n");
     966            // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable
     967            // ### Remove before release...
     968            static bool do_vectorpath_cache = qgetenv("QT_OPENGL_NO_PATH_CACHE").isEmpty();
     969            if (do_vectorpath_cache)
     970                path.makeCacheable();
     971            vertexCoordinateArray.clear();
     972            vertexCoordinateArray.addPath(path, inverseScale, false);
     973            prepareForDraw(currentBrush.isOpaque());
     974            drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
     975        }
     976
     977    } else {
    588978        // The path is too complicated & needs the stencil technique
    589         pathVertexArray.clear();
    590         pathVertexArray.addPath(path, inverseScale);
    591 
    592         fillStencilWithVertexArray(pathVertexArray, path.hasWindingFill());
     979        vertexCoordinateArray.clear();
     980        vertexCoordinateArray.addPath(path, inverseScale, false);
     981
     982        fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
     983
     984        glStencilMask(0xff);
     985        glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
     986
     987        if (q->state()->clipTestEnabled) {
     988            // Pass when high bit is set, replace stencil value with current clip
     989            glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT);
     990        } else if (path.hasWindingFill()) {
     991            // Pass when any bit is set, replace stencil value with 0
     992            glStencilFunc(GL_NOTEQUAL, 0, 0xff);
     993        } else {
     994            // Pass when high bit is set, replace stencil value with 0
     995            glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
     996        }
     997        prepareForDraw(currentBrush.isOpaque());
    593998
    594999        // Stencil the brush onto the dest buffer
    595         glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
    596         glEnable(GL_STENCIL_TEST);
    597         prepareForDraw();
    598         composite(pathVertexArray.boundingRect());
    599         glDisable(GL_STENCIL_TEST);
    600 
    601         cleanStencilBuffer(pathVertexArray.boundingRect());
    602     }
    603 }
    604 
    605 
    606 void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill)
    607 {
     1000        composite(vertexCoordinateArray.boundingRect());
     1001        glStencilMask(0);
     1002        updateClipScissorTest();
     1003    }
     1004}
     1005
     1006
     1007void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
     1008                                                          int count,
     1009                                                          int *stops,
     1010                                                          int stopCount,
     1011                                                          const QGLRect &bounds,
     1012                                                          StencilFillMode mode)
     1013{
     1014    Q_ASSERT(count || stops);
     1015
    6081016//     qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
    609     if (stencilBuferDirty) {
    610         // Clear the stencil buffer to zeros
    611         glDisable(GL_STENCIL_TEST);
    612         glStencilMask(0xFFFF); // Enable writing to stencil buffer, otherwise glClear wont do anything.
     1017    glStencilMask(0xff); // Enable stencil writes
     1018
     1019    if (dirtyStencilRegion.intersects(currentScissorBounds)) {
     1020        QVector<QRect> clearRegion = dirtyStencilRegion.intersected(currentScissorBounds).rects();
    6131021        glClearStencil(0); // Clear to zero
    614         glClear(GL_STENCIL_BUFFER_BIT);
    615         stencilBuferDirty = false;
     1022        for (int i = 0; i < clearRegion.size(); ++i) {
     1023#ifndef QT_GL_NO_SCISSOR_TEST
     1024            setScissor(clearRegion.at(i));
     1025#endif
     1026            glClear(GL_STENCIL_BUFFER_BIT);
     1027        }
     1028
     1029        dirtyStencilRegion -= currentScissorBounds;
     1030
     1031#ifndef QT_GL_NO_SCISSOR_TEST
     1032        updateClipScissorTest();
     1033#endif
    6161034    }
    6171035
    6181036    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
    619     glStencilMask(0xFFFF); // Enable stencil writes
    620     glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
    621 
    622     // Setup the stencil op:
    623     if (useWindingFill) {
    624         glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); // Inc. for front-facing triangle
    625         glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); //Dec. for back-facing "holes"
    626     } else
     1037    useSimpleShader();
     1038    glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d
     1039
     1040    if (mode == WindingFillMode) {
     1041        Q_ASSERT(stops && !count);
     1042        if (q->state()->clipTestEnabled) {
     1043            // Flatten clip values higher than current clip, and set high bit to match current clip
     1044            glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
     1045            glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
     1046            composite(bounds);
     1047
     1048            glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT);
     1049        } else if (!stencilClean) {
     1050            // Clear stencil buffer within bounding rect
     1051            glStencilFunc(GL_ALWAYS, 0, 0xff);
     1052            glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
     1053            composite(bounds);
     1054        }
     1055
     1056        // Inc. for front-facing triangle
     1057        glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP);
     1058        // Dec. for back-facing "holes"
     1059        glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP);
     1060        glStencilMask(~GL_STENCIL_HIGH_BIT);
     1061        drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
     1062
     1063        if (q->state()->clipTestEnabled) {
     1064            // Clear high bit of stencil outside of path
     1065            glStencilFunc(GL_EQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
     1066            glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
     1067            glStencilMask(GL_STENCIL_HIGH_BIT);
     1068            composite(bounds);
     1069        }
     1070    } else if (mode == OddEvenFillMode) {
     1071        glStencilMask(GL_STENCIL_HIGH_BIT);
    6271072        glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
    628 
    629     // No point in using a fancy gradiant shader for writing into the stencil buffer!
    630     useSimpleShader();
    631 
    632     glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d
    633     glDisable(GL_BLEND);
    634 
    635     // Draw the vertecies into the stencil buffer:
    636     drawVertexArrays(vertexArray, GL_TRIANGLE_FAN);
     1073        drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
     1074
     1075    } else { // TriStripStrokeFillMode
     1076        Q_ASSERT(count && !stops); // tristrips generated directly, so no vertexArray or stops
     1077        glStencilMask(GL_STENCIL_HIGH_BIT);
     1078#if 0
     1079        glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
     1080        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1081        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, data);
     1082        glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
     1083        glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1084#else
     1085
     1086        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
     1087        if (q->state()->clipTestEnabled) {
     1088            glStencilFunc(GL_LEQUAL, q->state()->currentClip | GL_STENCIL_HIGH_BIT,
     1089                          ~GL_STENCIL_HIGH_BIT);
     1090        } else {
     1091            glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
     1092        }
     1093        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1094        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, data);
     1095        glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
     1096        glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1097#endif
     1098    }
    6371099
    6381100    // Enable color writes & disable stencil writes
    6391101    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    640     glStencilMask(0);
    641 }
    642 
    643 void QGL2PaintEngineExPrivate::cleanStencilBuffer(const QGLRect& area)
    644 {
    645 //     qDebug("QGL2PaintEngineExPrivate::cleanStencilBuffer()");
     1102}
     1103
     1104/*
     1105    If the maximum value in the stencil buffer is GL_STENCIL_HIGH_BIT - 1,
     1106    restore the stencil buffer to a pristine state.  The current clip region
     1107    is set to 1, and the rest to 0.
     1108*/
     1109void QGL2PaintEngineExPrivate::resetClipIfNeeded()
     1110{
     1111    if (maxClip != (GL_STENCIL_HIGH_BIT - 1))
     1112        return;
     1113
     1114    Q_Q(QGL2PaintEngineEx);
     1115
    6461116    useSimpleShader();
    647 
    648     GLfloat rectVerts[] = {
    649         area.left,  area.top,
    650         area.left,  area.bottom,
    651         area.right, area.bottom,
    652         area.right, area.top
    653     };
    654 
    655     glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    656     glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, rectVerts);
    657 
    6581117    glEnable(GL_STENCIL_TEST);
    659     glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
    660 
    661     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
    662     glStencilMask(0xFFFF); // Enable writing to stencil buffer
    663     glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // Write 0's to stencil buffer
    664 
    665     glDisable(GL_BLEND);
    666 
    667     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    668 
    669     glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    670 
    671     // Enable color writes & disable stencil writes
     1118    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
     1119
     1120    QRectF bounds = q->state()->matrix.inverted().mapRect(QRectF(0, 0, width, height));
     1121    QGLRect rect(bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
     1122
     1123    // Set high bit on clip region
     1124    glStencilFunc(GL_LEQUAL, q->state()->currentClip, 0xff);
     1125    glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
     1126    glStencilMask(GL_STENCIL_HIGH_BIT);
     1127    composite(rect);
     1128
     1129    // Reset clipping to 1 and everything else to zero
     1130    glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT);
     1131    glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
     1132    glStencilMask(0xff);
     1133    composite(rect);
     1134
     1135    q->state()->currentClip = 1;
     1136    q->state()->canRestoreClip = false;
     1137
     1138    maxClip = 1;
     1139
     1140    glStencilMask(0x0);
    6721141    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    673     glStencilMask(0);
    674     glDisable(GL_STENCIL_TEST);
    675 }
    676 
    677 void QGL2PaintEngineExPrivate::prepareForDraw()
    678 {
    679     if (brushTextureDirty)
     1142}
     1143
     1144bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
     1145{
     1146    if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
    6801147        updateBrushTexture();
    6811148
     
    6831150        updateCompositionMode();
    6841151
    685     if (shaderManager->useCorrectShaderProg()) {
     1152    if (matrixDirty)
     1153        updateMatrix();
     1154
     1155    const bool stateHasOpacity = q->state()->opacity < 0.99f;
     1156    if (q->state()->composition_mode == QPainter::CompositionMode_Source
     1157        || (q->state()->composition_mode == QPainter::CompositionMode_SourceOver
     1158            && srcPixelsAreOpaque && !stateHasOpacity))
     1159    {
     1160        glDisable(GL_BLEND);
     1161    } else {
     1162        glEnable(GL_BLEND);
     1163    }
     1164
     1165    QGLEngineShaderManager::OpacityMode opacityMode;
     1166    if (mode == ImageArrayDrawingMode) {
     1167        opacityMode = QGLEngineShaderManager::AttributeOpacity;
     1168    } else {
     1169        opacityMode = stateHasOpacity ? QGLEngineShaderManager::UniformOpacity
     1170                                      : QGLEngineShaderManager::NoOpacity;
     1171        if (stateHasOpacity && (mode != ImageDrawingMode)) {
     1172            // Using a brush
     1173            bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
     1174                                  (currentBrush.style() <= Qt::DiagCrossPattern);
     1175
     1176            if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern)
     1177                opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader
     1178        }
     1179    }
     1180    shaderManager->setOpacityMode(opacityMode);
     1181
     1182    bool changed = shaderManager->useCorrectShaderProg();
     1183    // If the shader program needs changing, we change it and mark all uniforms as dirty
     1184    if (changed) {
    6861185        // The shader program has changed so mark all uniforms as dirty:
    6871186        brushUniformsDirty = true;
    688         brushShaderMatrixUniformDirty = true;
    689     }
    690 
    691     if (brushUniformsDirty)
     1187        shaderMatrixUniformDirty = true;
     1188        opacityUniformDirty = true;
     1189    }
     1190
     1191    if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
    6921192        updateBrushUniforms();
    6931193
    694     if (brushShaderMatrixUniformDirty) {
    695         shaderManager->brushShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
    696         brushShaderMatrixUniformDirty = false;
    697     }
    698 
    699     if ((q->state()->opacity < 0.99f) || !currentBrush->isOpaque())
    700         glEnable(GL_BLEND);
    701     else
    702         glDisable(GL_BLEND);
     1194    if (shaderMatrixUniformDirty) {
     1195        glUniformMatrix3fv(location(QGLEngineShaderManager::PmvMatrix), 1, GL_FALSE, (GLfloat*)pmvMatrix);
     1196        shaderMatrixUniformDirty = false;
     1197    }
     1198
     1199    if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
     1200        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
     1201        opacityUniformDirty = false;
     1202    }
     1203
     1204    return changed;
    7031205}
    7041206
     
    7221224
    7231225// Draws the vertex array as a set of <vertexArrayStops.size()> triangle fans.
    724 void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray, GLenum primitive)
     1226void QGL2PaintEngineExPrivate::drawVertexArrays(const float *data, int *stops, int stopCount,
     1227                                                GLenum primitive)
    7251228{
    7261229    // Now setup the pointer to the vertex array:
    7271230    glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    728     glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray.data());
     1231    glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, data);
    7291232
    7301233    int previousStop = 0;
    731     foreach(int stop, vertexArray.stops()) {
     1234    for (int i=0; i<stopCount; ++i) {
     1235        int stop = stops[i];
    7321236/*
    7331237        qDebug("Drawing triangle fan for vertecies %d -> %d:", previousStop, stop-1);
     
    7411245}
    7421246
    743 
    744 
    745 
    746 
    7471247/////////////////////////////////// Public Methods //////////////////////////////////////////
    7481248
     
    7501250    : QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
    7511251{
    752     qDebug("QGL2PaintEngineEx::QGL2PaintEngineEx()");
    753 
    7541252}
    7551253
     
    7621260    Q_D(QGL2PaintEngineEx);
    7631261
    764     QTime startTime = QTime::currentTime();
    765 
    766     d->setBrush(&brush);
     1262    if (qbrush_style(brush) == Qt::NoBrush)
     1263        return;
     1264    ensureActive();
     1265    d->setBrush(brush);
    7671266    d->fill(path);
    768     d->setBrush(&(state()->brush)); // reset back to the state's brush
    769 }
     1267}
     1268
     1269extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
     1270
    7701271
    7711272void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
     
    7731274    Q_D(QGL2PaintEngineEx);
    7741275
    775     if (pen.style() == Qt::NoPen)
     1276    const QBrush &penBrush = qpen_brush(pen);
     1277    if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush)
    7761278        return;
    7771279
    778     if ( (pen.isCosmetic() && (pen.style() == Qt::SolidLine)) && (pen.widthF() < 2.5f) )
    779     {
    780         // We only handle solid, cosmetic pens with a width of 1 pixel
    781         const QBrush& brush = pen.brush();
    782         d->setBrush(&brush);
    783 
    784         if (pen.widthF() < 0.01f)
    785             glLineWidth(1.0);
    786         else
    787             glLineWidth(pen.widthF());
    788 
    789         d->drawOutline(path);
    790         d->setBrush(&(state()->brush));
    791     } else
    792         return QPaintEngineEx::stroke(path, pen);
    793 
    794 }
    795 
    796 void QGL2PaintEngineEx::penChanged()
    797 {
    798 //    qDebug("QGL2PaintEngineEx::penChanged() not implemented!");
    799 }
    800 
    801 
    802 void QGL2PaintEngineEx::brushChanged()
    803 {
    804 //    qDebug("QGL2PaintEngineEx::brushChanged()");
    805     Q_D(QGL2PaintEngineEx);
    806     d->setBrush(&(state()->brush));
    807 }
    808 
    809 void QGL2PaintEngineEx::brushOriginChanged()
    810 {
    811 //    qDebug("QGL2PaintEngineEx::brushOriginChanged()");
    812     Q_D(QGL2PaintEngineEx);
    813     d->brushUniformsDirty = true;
    814 }
     1280    QOpenGL2PaintEngineState *s = state();
     1281    if (pen.isCosmetic() && !qt_scaleForTransform(s->transform(), 0)) {
     1282        // QTriangulatingStroker class is not meant to support cosmetically sheared strokes.
     1283        QPaintEngineEx::stroke(path, pen);
     1284        return;
     1285    }
     1286
     1287    ensureActive();
     1288    d->setBrush(penBrush);
     1289    d->stroke(path, pen);
     1290}
     1291
     1292void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
     1293{
     1294    const QOpenGL2PaintEngineState *s = q->state();
     1295    const bool newAddOffset = !(s->renderHints & QPainter::Antialiasing) && !multisamplingAlwaysEnabled;
     1296    if (addOffset != newAddOffset) {
     1297        addOffset = newAddOffset;
     1298        matrixDirty = true;
     1299    }
     1300
     1301    if (snapToPixelGrid) {
     1302        snapToPixelGrid = false;
     1303        matrixDirty = true;
     1304    }
     1305
     1306    const Qt::PenStyle penStyle = qpen_style(pen);
     1307    const QBrush &penBrush = qpen_brush(pen);
     1308    const bool opaque = penBrush.isOpaque() && s->opacity > 0.99;
     1309
     1310    transferMode(BrushDrawingMode);
     1311
     1312    // updateMatrix() is responsible for setting the inverse scale on
     1313    // the strokers, so we need to call it here and not wait for
     1314    // prepareForDraw() down below.
     1315    updateMatrix();
     1316
     1317    if (penStyle == Qt::SolidLine) {
     1318        stroker.process(path, pen);
     1319
     1320    } else { // Some sort of dash
     1321        dasher.process(path, pen);
     1322
     1323        QVectorPath dashStroke(dasher.points(),
     1324                               dasher.elementCount(),
     1325                               dasher.elementTypes());
     1326        stroker.process(dashStroke, pen);
     1327    }
     1328
     1329    if (opaque) {
     1330        prepareForDraw(opaque);
     1331        glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1332        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, false, 0, stroker.vertices());
     1333        glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2);
     1334
     1335//         QBrush b(Qt::green);
     1336//         d->setBrush(&b);
     1337//         d->prepareForDraw(true);
     1338//         glDrawArrays(GL_LINE_STRIP, 0, d->stroker.vertexCount() / 2);
     1339
     1340        glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1341
     1342    } else {
     1343        qreal width = qpen_widthf(pen) / 2;
     1344        if (width == 0)
     1345            width = 0.5;
     1346        qreal extra = pen.joinStyle() == Qt::MiterJoin
     1347                      ? qMax(pen.miterLimit() * width, width)
     1348                      : width;
     1349
     1350        if (pen.isCosmetic())
     1351            extra = extra * inverseScale;
     1352
     1353        QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra);
     1354
     1355        fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2,
     1356                                      0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode);
     1357
     1358        glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
     1359
     1360        // Pass when any bit is set, replace stencil value with 0
     1361        glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
     1362        prepareForDraw(false);
     1363
     1364        // Stencil the brush onto the dest buffer
     1365        composite(bounds);
     1366
     1367        glStencilMask(0);
     1368
     1369        updateClipScissorTest();
     1370    }
     1371}
     1372
     1373void QGL2PaintEngineEx::penChanged() { }
     1374void QGL2PaintEngineEx::brushChanged() { }
     1375void QGL2PaintEngineEx::brushOriginChanged() { }
    8151376
    8161377void QGL2PaintEngineEx::opacityChanged()
     
    8181379//    qDebug("QGL2PaintEngineEx::opacityChanged()");
    8191380    Q_D(QGL2PaintEngineEx);
     1381    state()->opacityChanged = true;
    8201382
    8211383    Q_ASSERT(d->shaderManager);
    822     d->shaderManager->setUseGlobalOpacity(state()->opacity > 0.999);
    8231384    d->brushUniformsDirty = true;
     1385    d->opacityUniformDirty = true;
    8241386}
    8251387
     
    8281390//     qDebug("QGL2PaintEngineEx::compositionModeChanged()");
    8291391    Q_D(QGL2PaintEngineEx);
     1392    state()->compositionModeChanged = true;
    8301393    d->compositionModeDirty = true;
    8311394}
     
    8331396void QGL2PaintEngineEx::renderHintsChanged()
    8341397{
     1398    state()->renderHintsChanged = true;
     1399
     1400#if !defined(QT_OPENGL_ES_2)
     1401    if ((state()->renderHints & QPainter::Antialiasing)
     1402        || (state()->renderHints & QPainter::HighQualityAntialiasing))
     1403        glEnable(GL_MULTISAMPLE);
     1404    else
     1405        glDisable(GL_MULTISAMPLE);
     1406#endif
     1407
     1408    Q_D(QGL2PaintEngineEx);
     1409    d->lastTextureUsed = GLuint(-1);
     1410    d->brushTextureDirty = true;
    8351411//    qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!");
    8361412}
     
    8401416    Q_D(QGL2PaintEngineEx);
    8411417    d->matrixDirty = true;
     1418    state()->matrixChanged = true;
    8421419}
    8431420
     
    8461423{
    8471424    Q_D(QGL2PaintEngineEx);
    848     glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
    849 
    850     d->ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
    851 
    852     //FIXME: we should use hasAlpha() instead, but that's SLOW at the moment
    853     if ((state()->opacity < 0.99f) || pixmap.hasAlphaChannel())
    854         glEnable(GL_BLEND);
    855     else
    856         glDisable(GL_BLEND);
    857 
    858     d->drawTexture(dest, src, pixmap.width(), pixmap.height());
     1425    ensureActive();
     1426    d->transferMode(ImageDrawingMode);
     1427
     1428    QGLContext *ctx = d->ctx;
     1429    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     1430    QGLTexture *texture =
     1431        ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
     1432                                   QGLContext::InternalBindOption
     1433                                   | QGLContext::CanFlipNativePixmapBindOption);
     1434
     1435    GLfloat top = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.top()) : src.top();
     1436    GLfloat bottom = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.bottom()) : src.bottom();
     1437    QGLRect srcRect(src.left(), top, src.right(), bottom);
     1438
     1439    bool isBitmap = pixmap.isQBitmap();
     1440    bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
     1441
     1442    d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     1443                           state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
     1444    d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
    8591445}
    8601446
     
    8631449{
    8641450    Q_D(QGL2PaintEngineEx);
    865     glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
    866     d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
    867 
    868     if ((state()->opacity < 0.99f) || image.hasAlphaChannel())
    869         glEnable(GL_BLEND);
    870     else
    871         glDisable(GL_BLEND);
    872 
    873     d->drawTexture(dest, src, image.width(), image.height());
     1451    ensureActive();
     1452    d->transferMode(ImageDrawingMode);
     1453
     1454    QGLContext *ctx = d->ctx;
     1455    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     1456    QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
     1457    GLuint id = texture->id;
     1458
     1459    d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     1460                           state()->renderHints & QPainter::SmoothPixmapTransform, id);
     1461    d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
     1462}
     1463
     1464void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
     1465{
     1466    Q_D(QGL2PaintEngineEx);
     1467    ensureActive();
     1468    d->transferMode(ImageDrawingMode);
     1469
     1470#ifndef QT_OPENGL_ES_2
     1471    QGLContext *ctx = d->ctx;
     1472#endif
     1473    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     1474    glBindTexture(GL_TEXTURE_2D, textureId);
     1475
     1476    QGLRect srcRect(src.left(), src.bottom(), src.right(), src.top());
     1477
     1478    d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     1479                           state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
     1480    d->drawTexture(dest, srcRect, size, false);
    8741481}
    8751482
    8761483void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
    8771484{
    878     QOpenGLPaintEngineState *s = state();
     1485    Q_D(QGL2PaintEngineEx);
     1486
     1487    ensureActive();
     1488    QOpenGL2PaintEngineState *s = state();
    8791489
    8801490    const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
    8811491
    882     bool drawCached = true;
    883 
    884     if (state()->pen.brush().style() != Qt::SolidPattern)
     1492    QTransform::TransformationType txtype = s->matrix.type();
     1493
     1494    float det = s->matrix.determinant();
     1495    bool drawCached = txtype < QTransform::TxProject;
     1496
     1497    // don't try to cache huge fonts or vastly transformed fonts
     1498    const qreal pixelSize = ti.fontEngine->fontDef.pixelSize;
     1499    if (pixelSize * pixelSize * qAbs(det) >= 64 * 64 || det < 0.25f || det > 4.f)
    8851500        drawCached = false;
    8861501
    887     if (s->matrix.type() > QTransform::TxTranslate)
     1502    QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
     1503                                            ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
     1504                                            : d->glyphCacheType;
     1505
     1506    if (txtype > QTransform::TxTranslate)
     1507        glyphType = QFontEngineGlyphCache::Raster_A8;
     1508
     1509    if (glyphType == QFontEngineGlyphCache::Raster_RGBMask
     1510        && state()->composition_mode != QPainter::CompositionMode_Source
     1511        && state()->composition_mode != QPainter::CompositionMode_SourceOver)
     1512    {
    8881513        drawCached = false;
    889 
    890     // don't try to cache huge fonts
    891     if (ti.fontEngine->fontDef.pixelSize * qSqrt(s->matrix.determinant()) >= 64)
    892         drawCached = false;
     1514    }
    8931515
    8941516    if (drawCached) {
    895         drawCachedGlyphs(p, ti);
     1517        d->drawCachedGlyphs(p, glyphType, ti);
    8961518        return;
    8971519    }
     
    9001522}
    9011523
    902 void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
    903 {
    904     Q_D(QGL2PaintEngineEx);
    905     QOpenGLPaintEngineState *s = state();
     1524void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType,
     1525                                                const QTextItemInt &ti)
     1526{
     1527    Q_Q(QGL2PaintEngineEx);
    9061528
    9071529    QVarLengthArray<QFixedPoint> positions;
    9081530    QVarLengthArray<glyph_t> glyphs;
    909     QTransform matrix;
    910     matrix.translate(p.x(), p.y());
     1531    QTransform matrix = QTransform::fromTranslate(p.x(), p.y());
    9111532    ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
    9121533
    913     QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
    914         ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
    915         : QFontEngineGlyphCache::Raster_A8;
    916 
    917     QImageTextureGlyphCache *cache =
    918         (QImageTextureGlyphCache *) ti.fontEngine->glyphCache(glyphType, s->matrix);
    919     if (!cache) {
    920         cache = new QImageTextureGlyphCache(glyphType, s->matrix);
    921         ti.fontEngine->setGlyphCache(glyphType, cache);
    922     }
    923 
     1534    QGLTextureGlyphCache *cache =
     1535            (QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, glyphType, QTransform());
     1536
     1537    if (!cache || cache->cacheType() != glyphType) {
     1538        cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform());
     1539        ti.fontEngine->setGlyphCache(ctx, cache);
     1540    }
     1541
     1542    cache->setPaintEnginePrivate(this);
    9241543    cache->populate(ti, glyphs, positions);
    9251544
    926     const QImage &image = cache->image();
     1545    if (cache->width() == 0 || cache->height() == 0)
     1546        return;
     1547
     1548    transferMode(TextDrawingMode);
     1549
    9271550    int margin = cache->glyphMargin();
    9281551
    929     glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
    930     d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
    931 
    932     glEnable(GL_BLEND);
    933 
    934     d->shaderManager->textShader()->use();
    935     d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
    936 
    937     if (d->compositionModeDirty)
    938         d->updateCompositionMode();
    939 
    940     if (d->matrixDirty)
    941         d->updateMatrix();
    942 
    943     if (d->textShaderMatrixUniformDirty) {
    944         d->shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = d->pmvMatrix;
    945         d->textShaderMatrixUniformDirty = false;
    946     }
    947 
    948     d->shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
    949     QColor col = d->premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
    950     d->shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
    951 
    952     GLfloat dx = 1.0 / image.width();
    953     GLfloat dy = 1.0 / image.height();
    954 
    955     glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
    956     glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     1552    GLfloat dx = 1.0 / cache->width();
     1553    GLfloat dy = 1.0 / cache->height();
     1554
     1555    QGLPoint *oldVertexCoordinateDataPtr = vertexCoordinateArray.data();
     1556    QGLPoint *oldTextureCoordinateDataPtr = textureCoordinateArray.data();
     1557
     1558    vertexCoordinateArray.clear();
     1559    textureCoordinateArray.clear();
     1560
    9571561    for (int i=0; i<glyphs.size(); ++i) {
    9581562        const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
     
    9601564        int y = positions[i].y.toInt() - c.baseLineY - margin;
    9611565
    962         QGLRect dest = QRectF(x, y, c.w, c.h);
    963         QGLRect src = QRectF(c.x, c.y, c.w, c.h);
    964 
    965         GLfloat vertexCoords[] = {
    966             dest.left,  dest.top,
    967             dest.left,  dest.bottom,
    968             dest.right, dest.bottom,
    969             dest.right, dest.top
    970         };
    971 
    972         glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
    973 
    974         QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
    975 
    976         GLfloat textureCoords[] = {
    977             srcTextureRect.left,  srcTextureRect.top,
    978             srcTextureRect.left,  srcTextureRect.bottom,
    979             srcTextureRect.right, srcTextureRect.bottom,
    980             srcTextureRect.right, srcTextureRect.top
    981         };
    982 
    983         glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
    984 
    985         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    986     }
    987     glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
    988     glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     1566        vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
     1567        textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
     1568    }
     1569
     1570    if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
     1571        glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
     1572    if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
     1573        glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
     1574
     1575    if (addOffset) {
     1576        addOffset = false;
     1577        matrixDirty = true;
     1578    }
     1579    if (!snapToPixelGrid) {
     1580        snapToPixelGrid = true;
     1581        matrixDirty = true;
     1582    }
     1583
     1584    QBrush pensBrush = q->state()->pen.brush();
     1585    setBrush(pensBrush);
     1586
     1587    if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) {
     1588
     1589        // Subpixel antialiasing without gamma correction
     1590
     1591        QPainter::CompositionMode compMode = q->state()->composition_mode;
     1592        Q_ASSERT(compMode == QPainter::CompositionMode_Source
     1593            || compMode == QPainter::CompositionMode_SourceOver);
     1594
     1595        shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass1);
     1596
     1597        if (pensBrush.style() == Qt::SolidPattern) {
     1598            // Solid patterns can get away with only one pass.
     1599            QColor c = pensBrush.color();
     1600            qreal oldOpacity = q->state()->opacity;
     1601            if (compMode == QPainter::CompositionMode_Source) {
     1602                c = qt_premultiplyColor(c, q->state()->opacity);
     1603                q->state()->opacity = 1;
     1604                opacityUniformDirty = true;
     1605            }
     1606
     1607            compositionModeDirty = false; // I can handle this myself, thank you very much
     1608            prepareForDraw(false); // Text always causes src pixels to be transparent
     1609
     1610            // prepareForDraw() have set the opacity on the current shader, so the opacity state can now be reset.
     1611            if (compMode == QPainter::CompositionMode_Source) {
     1612                q->state()->opacity = oldOpacity;
     1613                opacityUniformDirty = true;
     1614            }
     1615
     1616            glEnable(GL_BLEND);
     1617            glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
     1618            glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
     1619        } else {
     1620            // Other brush styles need two passes.
     1621
     1622            qreal oldOpacity = q->state()->opacity;
     1623            if (compMode == QPainter::CompositionMode_Source) {
     1624                q->state()->opacity = 1;
     1625                opacityUniformDirty = true;
     1626                pensBrush = Qt::white;
     1627                setBrush(pensBrush);
     1628            }
     1629
     1630            compositionModeDirty = false; // I can handle this myself, thank you very much
     1631            prepareForDraw(false); // Text always causes src pixels to be transparent
     1632            glEnable(GL_BLEND);
     1633            glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
     1634
     1635            glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
     1636            glBindTexture(GL_TEXTURE_2D, cache->texture());
     1637            updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
     1638
     1639            shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT);
     1640            glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
     1641
     1642            shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
     1643
     1644            if (compMode == QPainter::CompositionMode_Source) {
     1645                q->state()->opacity = oldOpacity;
     1646                opacityUniformDirty = true;
     1647                pensBrush = q->state()->pen.brush();
     1648                setBrush(pensBrush);
     1649            }
     1650
     1651            compositionModeDirty = false;
     1652            prepareForDraw(false); // Text always causes src pixels to be transparent
     1653            glEnable(GL_BLEND);
     1654            glBlendFunc(GL_ONE, GL_ONE);
     1655        }
     1656        compositionModeDirty = true;
     1657    } else {
     1658        // Greyscale/mono glyphs
     1659
     1660        shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
     1661        prepareForDraw(false); // Text always causes src pixels to be transparent
     1662    }
     1663    //### TODO: Gamma correction
     1664
     1665    glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
     1666    glBindTexture(GL_TEXTURE_2D, cache->texture());
     1667    updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
     1668
     1669    shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT);
     1670    glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
     1671}
     1672
     1673void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
     1674{
     1675    Q_D(QGL2PaintEngineEx);
     1676    // Use fallback for extended composition modes.
     1677    if (state()->composition_mode > QPainter::CompositionMode_Plus) {
     1678        QPaintEngineEx::drawPixmaps(drawingData, dataCount, pixmap, hints);
     1679        return;
     1680    }
     1681
     1682    ensureActive();
     1683    d->drawPixmaps(drawingData, dataCount, pixmap, hints);
     1684}
     1685
     1686
     1687void QGL2PaintEngineExPrivate::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints)
     1688{
     1689    GLfloat dx = 1.0f / pixmap.size().width();
     1690    GLfloat dy = 1.0f / pixmap.size().height();
     1691
     1692    vertexCoordinateArray.clear();
     1693    textureCoordinateArray.clear();
     1694    opacityArray.reset();
     1695
     1696    if (addOffset) {
     1697        addOffset = false;
     1698        matrixDirty = true;
     1699    }
     1700
     1701    if (snapToPixelGrid) {
     1702        snapToPixelGrid = false;
     1703        matrixDirty = true;
     1704    }
     1705
     1706    bool allOpaque = true;
     1707
     1708    for (int i = 0; i < dataCount; ++i) {
     1709        qreal s = 0;
     1710        qreal c = 1;
     1711        if (drawingData[i].rotation != 0) {
     1712            s = qFastSin(drawingData[i].rotation * Q_PI / 180);
     1713            c = qFastCos(drawingData[i].rotation * Q_PI / 180);
     1714        }
     1715
     1716        qreal right = 0.5 * drawingData[i].scaleX * drawingData[i].source.width();
     1717        qreal bottom = 0.5 * drawingData[i].scaleY * drawingData[i].source.height();
     1718        QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
     1719        QGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c);
     1720
     1721        vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
     1722        vertexCoordinateArray.lineToArray(-bottomLeft.x + drawingData[i].point.x(), -bottomLeft.y + drawingData[i].point.y());
     1723        vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
     1724        vertexCoordinateArray.lineToArray(-bottomRight.x + drawingData[i].point.x(), -bottomRight.y + drawingData[i].point.y());
     1725        vertexCoordinateArray.lineToArray(bottomLeft.x + drawingData[i].point.x(), bottomLeft.y + drawingData[i].point.y());
     1726        vertexCoordinateArray.lineToArray(bottomRight.x + drawingData[i].point.x(), bottomRight.y + drawingData[i].point.y());
     1727
     1728        QGLRect src(drawingData[i].source.left() * dx, drawingData[i].source.top() * dy,
     1729                    drawingData[i].source.right() * dx, drawingData[i].source.bottom() * dy);
     1730
     1731        textureCoordinateArray.lineToArray(src.right, src.bottom);
     1732        textureCoordinateArray.lineToArray(src.right, src.top);
     1733        textureCoordinateArray.lineToArray(src.left, src.top);
     1734        textureCoordinateArray.lineToArray(src.left, src.top);
     1735        textureCoordinateArray.lineToArray(src.left, src.bottom);
     1736        textureCoordinateArray.lineToArray(src.right, src.bottom);
     1737
     1738        qreal opacity = drawingData[i].opacity * q->state()->opacity;
     1739        opacityArray << opacity << opacity << opacity << opacity << opacity << opacity;
     1740        allOpaque &= (opacity >= 0.99f);
     1741    }
     1742
     1743    glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
     1744    QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
     1745                                                     QGLContext::InternalBindOption
     1746                                                     | QGLContext::CanFlipNativePixmapBindOption);
     1747
     1748    if (texture->options & QGLContext::InvertedYBindOption) {
     1749        // Flip texture y-coordinate.
     1750        QGLPoint *data = textureCoordinateArray.data();
     1751        for (int i = 0; i < 6 * dataCount; ++i)
     1752            data[i].y = 1 - data[i].y;
     1753    }
     1754
     1755    transferMode(ImageArrayDrawingMode);
     1756
     1757    bool isBitmap = pixmap.isQBitmap();
     1758    bool isOpaque = !isBitmap && (!pixmap.hasAlphaChannel() || (hints & QDrawPixmaps::OpaqueHint)) && allOpaque;
     1759
     1760    updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
     1761                           q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
     1762
     1763    // Setup for texture drawing
     1764    currentBrush = noBrush;
     1765    shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
     1766    if (prepareForDraw(isOpaque))
     1767        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
     1768
     1769    if (isBitmap) {
     1770        QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
     1771        shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
     1772    }
     1773
     1774    glDrawArrays(GL_TRIANGLES, 0, 6 * dataCount);
    9891775}
    9901776
     
    9941780
    9951781//     qDebug("QGL2PaintEngineEx::begin()");
    996 
    997     QGLWidget* widget = static_cast<QGLWidget*>(pdev);
    998     d->ctx = const_cast<QGLContext*>(widget->context());
    999     d->ctx->makeCurrent();
    1000     d->width = widget->width();
    1001     d->height = widget->height();
    1002 
    1003     if (!d->shaderManager)
    1004         d->shaderManager = new QGLPEXShaderManager(d->ctx);
    1005 
    1006     glViewport(0, 0, d->width, d->height);
    1007 
    1008 //     glClearColor(0.0, 1.0, 0.0, 1.0);
    1009 //     glClear(GL_COLOR_BUFFER_BIT);
    1010 //     d->ctx->swapBuffers();
    1011 //     qDebug("You should see green now");
    1012 //     sleep(5);
    1013 
     1782    if (pdev->devType() == QInternal::OpenGL)
     1783        d->device = static_cast<QGLPaintDevice*>(pdev);
     1784    else
     1785        d->device = QGLPaintDevice::getDevice(pdev);
     1786
     1787    if (!d->device)
     1788        return false;
     1789
     1790    d->ctx = d->device->context();
     1791    d->ctx->d_ptr->active_engine = this;
     1792
     1793    const QSize sz = d->device->size();
     1794    d->width = sz.width();
     1795    d->height = sz.height();
     1796    d->mode = BrushDrawingMode;
    10141797    d->brushTextureDirty = true;
    10151798    d->brushUniformsDirty = true;
    10161799    d->matrixDirty = true;
    10171800    d->compositionModeDirty = true;
    1018     d->stencilBuferDirty = true;
    1019 
    1020     d->use_system_clip = !systemClip().isEmpty();
    1021 
     1801    d->opacityUniformDirty = true;
     1802    d->needsSync = true;
     1803    d->useSystemClip = !systemClip().isEmpty();
     1804    d->currentBrush = QBrush();
     1805
     1806    d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
     1807    d->stencilClean = true;
     1808
     1809    // Calling begin paint should make the correct context current. So, any
     1810    // code which calls into GL or otherwise needs a current context *must*
     1811    // go after beginPaint:
     1812    d->device->beginPaint();
     1813
     1814#if !defined(QT_OPENGL_ES_2)
     1815    bool success = qt_resolve_version_2_0_functions(d->ctx)
     1816                   && qt_resolve_buffer_extensions(d->ctx);
     1817    Q_ASSERT(success);
     1818    Q_UNUSED(success);
     1819#endif
     1820
     1821    d->shaderManager = new QGLEngineShaderManager(d->ctx);
     1822
     1823    glDisable(GL_STENCIL_TEST);
    10221824    glDisable(GL_DEPTH_TEST);
     1825    glDisable(GL_SCISSOR_TEST);
     1826
     1827#if !defined(QT_OPENGL_ES_2)
     1828    glDisable(GL_MULTISAMPLE);
     1829#endif
     1830
     1831    d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
     1832
     1833#if !defined(QT_OPENGL_ES_2)
     1834#if defined(Q_WS_WIN)
     1835    if (qt_cleartype_enabled)
     1836#endif
     1837        d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
     1838#endif
     1839
     1840#if defined(QT_OPENGL_ES_2)
     1841    // OpenGL ES can't switch MSAA off, so if the gl paint device is
     1842    // multisampled, it's always multisampled.
     1843    d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers();
     1844#else
     1845    d->multisamplingAlwaysEnabled = false;
     1846#endif
    10231847
    10241848    return true;
     
    10281852{
    10291853    Q_D(QGL2PaintEngineEx);
    1030     d->ctx->swapBuffers();
     1854    QGLContext *ctx = d->ctx;
     1855
     1856    glUseProgram(0);
     1857    d->transferMode(BrushDrawingMode);
     1858    d->device->endPaint();
     1859
     1860#if defined(Q_WS_X11)
     1861    // On some (probably all) drivers, deleting an X pixmap which has been bound to a texture
     1862    // before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes
     1863    // the pixmap behind the driver's back before it's had a chance to use it. To fix this, we
     1864    // reference all QPixmaps which have been bound to stop them being deleted and only deref
     1865    // them here, after swapBuffers, where they can be safely deleted.
     1866    ctx->d_func()->boundPixmaps.clear();
     1867#endif
     1868    d->ctx->d_ptr->active_engine = 0;
     1869
     1870    d->resetGLState();
     1871
     1872    delete d->shaderManager;
     1873    d->shaderManager = 0;
     1874
     1875#ifdef QT_OPENGL_CACHE_AS_VBOS
     1876    if (!d->unusedVBOSToClean.isEmpty()) {
     1877        glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
     1878        d->unusedVBOSToClean.clear();
     1879    }
     1880#endif
     1881
    10311882    return false;
    10321883}
    10331884
    1034 
    1035 /////////////////////////////////// State/Clipping stolen from QOpenGLPaintEngine //////////////////////////////////////////
     1885void QGL2PaintEngineEx::ensureActive()
     1886{
     1887    Q_D(QGL2PaintEngineEx);
     1888    QGLContext *ctx = d->ctx;
     1889
     1890    if (isActive() && ctx->d_ptr->active_engine != this) {
     1891        ctx->d_ptr->active_engine = this;
     1892        d->needsSync = true;
     1893    }
     1894
     1895    d->device->ensureActiveTarget();
     1896
     1897    if (d->needsSync) {
     1898        d->transferMode(BrushDrawingMode);
     1899        glViewport(0, 0, d->width, d->height);
     1900        d->needsSync = false;
     1901        d->shaderManager->setDirty();
     1902        setState(state());
     1903    }
     1904}
     1905
     1906void QGL2PaintEngineExPrivate::updateClipScissorTest()
     1907{
     1908    Q_Q(QGL2PaintEngineEx);
     1909    if (q->state()->clipTestEnabled) {
     1910        glEnable(GL_STENCIL_TEST);
     1911        glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
     1912    } else {
     1913        glDisable(GL_STENCIL_TEST);
     1914        glStencilFunc(GL_ALWAYS, 0, 0xff);
     1915    }
     1916
     1917#ifdef QT_GL_NO_SCISSOR_TEST
     1918    currentScissorBounds = QRect(0, 0, width, height);
     1919#else
     1920    QRect bounds = q->state()->rectangleClip;
     1921    if (!q->state()->clipEnabled) {
     1922        if (useSystemClip)
     1923            bounds = systemClip.boundingRect();
     1924        else
     1925            bounds = QRect(0, 0, width, height);
     1926    } else {
     1927        if (useSystemClip)
     1928            bounds = bounds.intersected(systemClip.boundingRect());
     1929        else
     1930            bounds = bounds.intersected(QRect(0, 0, width, height));
     1931    }
     1932
     1933    currentScissorBounds = bounds;
     1934
     1935    if (bounds == QRect(0, 0, width, height)) {
     1936        glDisable(GL_SCISSOR_TEST);
     1937    } else {
     1938        glEnable(GL_SCISSOR_TEST);
     1939        setScissor(bounds);
     1940    }
     1941#endif
     1942}
     1943
     1944void QGL2PaintEngineExPrivate::setScissor(const QRect &rect)
     1945{
     1946    const int left = rect.left();
     1947    const int width = rect.width();
     1948    const int bottom = height - (rect.top() + rect.height());
     1949    const int height = rect.height();
     1950
     1951    glScissor(left, bottom, width, height);
     1952}
    10361953
    10371954void QGL2PaintEngineEx::clipEnabledChanged()
     
    10391956    Q_D(QGL2PaintEngineEx);
    10401957
    1041     d->updateDepthClip();
     1958    state()->clipChanged = true;
     1959
     1960    if (painter()->hasClipping())
     1961        d->regenerateClip();
     1962    else
     1963        d->systemStateChanged();
     1964}
     1965
     1966void QGL2PaintEngineExPrivate::clearClip(uint value)
     1967{
     1968    dirtyStencilRegion -= currentScissorBounds;
     1969
     1970    glStencilMask(0xff);
     1971    glClearStencil(value);
     1972    glClear(GL_STENCIL_BUFFER_BIT);
     1973    glStencilMask(0x0);
     1974
     1975    q->state()->needsClipBufferClear = false;
     1976}
     1977
     1978void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
     1979{
     1980    transferMode(BrushDrawingMode);
     1981
     1982    if (addOffset) {
     1983        addOffset = false;
     1984        matrixDirty = true;
     1985    }
     1986    if (snapToPixelGrid) {
     1987        snapToPixelGrid = false;
     1988        matrixDirty = true;
     1989    }
     1990
     1991    if (matrixDirty)
     1992        updateMatrix();
     1993
     1994    stencilClean = false;
     1995
     1996    const bool singlePass = !path.hasWindingFill()
     1997        && (((q->state()->currentClip == maxClip - 1) && q->state()->clipTestEnabled)
     1998            || q->state()->needsClipBufferClear);
     1999    const uint referenceClipValue = q->state()->needsClipBufferClear ? 1 : q->state()->currentClip;
     2000
     2001    if (q->state()->needsClipBufferClear)
     2002        clearClip(1);
     2003
     2004    if (path.isEmpty()) {
     2005        glEnable(GL_STENCIL_TEST);
     2006        glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
     2007        return;
     2008    }
     2009
     2010    if (q->state()->clipTestEnabled)
     2011        glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
     2012    else
     2013        glStencilFunc(GL_ALWAYS, 0, 0xff);
     2014
     2015    vertexCoordinateArray.clear();
     2016    vertexCoordinateArray.addPath(path, inverseScale, false);
     2017
     2018    if (!singlePass)
     2019        fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
     2020
     2021    glColorMask(false, false, false, false);
     2022    glEnable(GL_STENCIL_TEST);
     2023    useSimpleShader();
     2024
     2025    if (singlePass) {
     2026        // Under these conditions we can set the new stencil value in a single
     2027        // pass, by using the current value and the "new value" as the toggles
     2028
     2029        glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT);
     2030        glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
     2031        glStencilMask(value ^ referenceClipValue);
     2032
     2033        drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
     2034    } else {
     2035        glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
     2036        glStencilMask(0xff);
     2037
     2038        if (!q->state()->clipTestEnabled && path.hasWindingFill()) {
     2039            // Pass when any clip bit is set, set high bit
     2040            glStencilFunc(GL_NOTEQUAL, GL_STENCIL_HIGH_BIT, ~GL_STENCIL_HIGH_BIT);
     2041            composite(vertexCoordinateArray.boundingRect());
     2042        }
     2043
     2044        // Pass when high bit is set, replace stencil value with new clip value
     2045        glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT);
     2046
     2047        composite(vertexCoordinateArray.boundingRect());
     2048    }
     2049
     2050    glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
     2051    glStencilMask(0);
     2052
     2053    glColorMask(true, true, true, true);
    10422054}
    10432055
     
    10452057{
    10462058//     qDebug("QGL2PaintEngineEx::clip()");
    1047     const qreal *points = path.points();
    1048     const QPainterPath::ElementType *types = path.elements();
    1049     if (!types && path.shape() == QVectorPath::RectangleHint) {
    1050         QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
    1051         updateClipRegion(QRegion(r.toRect()), op);
    1052         return;
    1053     }
    1054 
    1055     QPainterPath p;
    1056     if (types) {
    1057         int id = 0;
    1058         for (int i=0; i<path.elementCount(); ++i) {
    1059             switch(types[i]) {
    1060             case QPainterPath::MoveToElement:
    1061                 p.moveTo(QPointF(points[id], points[id+1]));
    1062                 id+=2;
    1063                 break;
    1064             case QPainterPath::LineToElement:
    1065                 p.lineTo(QPointF(points[id], points[id+1]));
    1066                 id+=2;
    1067                 break;
    1068             case QPainterPath::CurveToElement: {
    1069                 QPointF p1(points[id], points[id+1]);
    1070                 QPointF p2(points[id+2], points[id+3]);
    1071                 QPointF p3(points[id+4], points[id+5]);
    1072                 p.cubicTo(p1, p2, p3);
    1073                 id+=6;
    1074                 break;
    1075             }
    1076             case QPainterPath::CurveToDataElement:
    1077                 ;
    1078                 break;
    1079             }
    1080         }
    1081     } else if (!path.isEmpty()) {
    1082         p.moveTo(QPointF(points[0], points[1]));
    1083         int id = 2;
    1084         for (int i=1; i<path.elementCount(); ++i) {
    1085             p.lineTo(QPointF(points[id], points[id+1]));
    1086             id+=2;
    1087         }
    1088     }
    1089     if (path.hints() & QVectorPath::WindingFill)
    1090         p.setFillRule(Qt::WindingFill);
    1091 
    1092     updateClipRegion(QRegion(p.toFillPolygon().toPolygon(), p.fillRule()), op);
    1093     return;
    1094 }
    1095 
    1096 void QGL2PaintEngineEx::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op)
    1097 {
    1098 //     qDebug("QGL2PaintEngineEx::updateClipRegion()");
    10992059    Q_D(QGL2PaintEngineEx);
    11002060
    1101     QRegion sysClip = systemClip();
    1102     if (op == Qt::NoClip && !d->use_system_clip) {
    1103         state()->hasClipping = false;
    1104         state()->clipRegion = QRegion();
    1105         d->updateDepthClip();
    1106         return;
    1107     }
    1108 
    1109     bool isScreenClip = false;
    1110     if (!d->use_system_clip) {
    1111         QVector<QRect> untransformedRects = clipRegion.rects();
    1112 
    1113         if (untransformedRects.size() == 1) {
    1114             QPainterPath path;
    1115             path.addRect(untransformedRects[0]);
    1116             //path = d->matrix.map(path);
    1117             path = state()->matrix.map(path);
    1118 
    1119 //             if (path.contains(QRectF(QPointF(), d->drawable.size())))
    1120 //                 isScreenClip = true;
    1121             if (path.contains(QRectF(0.0, 0.0, d->width, d->height)))
    1122                 isScreenClip = true;
    1123         }
    1124     }
    1125 
    1126 //     QRegion region = isScreenClip ? QRegion() : clipRegion * d->matrix;
    1127     QRegion region = isScreenClip ? QRegion() : clipRegion * state()->matrix;
     2061    state()->clipChanged = true;
     2062
     2063    ensureActive();
     2064
     2065    if (op == Qt::ReplaceClip) {
     2066        op = Qt::IntersectClip;
     2067        if (d->hasClipOperations()) {
     2068            d->systemStateChanged();
     2069            state()->canRestoreClip = false;
     2070        }
     2071    }
     2072
     2073#ifndef QT_GL_NO_SCISSOR_TEST
     2074    if (!path.isEmpty() && op == Qt::IntersectClip && (path.shape() == QVectorPath::RectangleHint)) {
     2075        const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
     2076        QRectF rect(points[0], points[2]);
     2077
     2078        if (state()->matrix.type() <= QTransform::TxScale) {
     2079            state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect());
     2080            d->updateClipScissorTest();
     2081            return;
     2082        }
     2083    }
     2084#endif
     2085
     2086    const QRect pathRect = state()->matrix.mapRect(path.controlPointRect()).toAlignedRect();
     2087
    11282088    switch (op) {
    11292089    case Qt::NoClip:
    1130         if (!d->use_system_clip)
    1131             break;
    1132         state()->clipRegion = sysClip;
     2090        if (d->useSystemClip) {
     2091            state()->clipTestEnabled = true;
     2092            state()->currentClip = 1;
     2093        } else {
     2094            state()->clipTestEnabled = false;
     2095        }
     2096        state()->rectangleClip = QRect(0, 0, d->width, d->height);
     2097        state()->canRestoreClip = false;
     2098        d->updateClipScissorTest();
    11332099        break;
    11342100    case Qt::IntersectClip:
    1135         if (isScreenClip)
    1136             return;
    1137         if (state()->hasClipping) {
    1138             state()->clipRegion &= region;
    1139             break;
    1140         }
    1141         // fall through
    1142     case Qt::ReplaceClip:
    1143         if (d->use_system_clip && !sysClip.isEmpty())
    1144             state()->clipRegion = region & sysClip;
    1145         else
    1146             state()->clipRegion = region;
     2101        state()->rectangleClip = state()->rectangleClip.intersected(pathRect);
     2102        d->updateClipScissorTest();
     2103        d->resetClipIfNeeded();
     2104        ++d->maxClip;
     2105        d->writeClip(path, d->maxClip);
     2106        state()->currentClip = d->maxClip;
     2107        state()->clipTestEnabled = true;
    11472108        break;
    1148     case Qt::UniteClip:
    1149         state()->clipRegion |= region;
    1150         if (d->use_system_clip && !sysClip.isEmpty())
    1151             state()->clipRegion &= sysClip;
     2109    case Qt::UniteClip: {
     2110        d->resetClipIfNeeded();
     2111        ++d->maxClip;
     2112        if (state()->rectangleClip.isValid()) {
     2113            QPainterPath path;
     2114            path.addRect(state()->rectangleClip);
     2115
     2116            // flush the existing clip rectangle to the depth buffer
     2117            d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxClip);
     2118        }
     2119
     2120        state()->clipTestEnabled = false;
     2121#ifndef QT_GL_NO_SCISSOR_TEST
     2122        QRect oldRectangleClip = state()->rectangleClip;
     2123
     2124        state()->rectangleClip = state()->rectangleClip.united(pathRect);
     2125        d->updateClipScissorTest();
     2126
     2127        QRegion extendRegion = QRegion(state()->rectangleClip) - oldRectangleClip;
     2128
     2129        if (!extendRegion.isEmpty()) {
     2130            QPainterPath extendPath;
     2131            extendPath.addRegion(extendRegion);
     2132
     2133            // first clear the depth buffer in the extended region
     2134            d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(extendPath)), 0);
     2135        }
     2136#endif
     2137        // now write the clip path
     2138        d->writeClip(path, d->maxClip);
     2139        state()->canRestoreClip = false;
     2140        state()->currentClip = d->maxClip;
     2141        state()->clipTestEnabled = true;
    11522142        break;
     2143        }
    11532144    default:
    11542145        break;
    11552146    }
    1156 
    1157     if (isScreenClip) {
    1158         state()->hasClipping = false;
    1159         state()->clipRegion = QRegion();
     2147}
     2148
     2149void QGL2PaintEngineExPrivate::regenerateClip()
     2150{
     2151    systemStateChanged();
     2152    replayClipOperations();
     2153}
     2154
     2155void QGL2PaintEngineExPrivate::systemStateChanged()
     2156{
     2157    Q_Q(QGL2PaintEngineEx);
     2158
     2159    q->state()->clipChanged = true;
     2160
     2161    if (systemClip.isEmpty()) {
     2162        useSystemClip = false;
    11602163    } else {
    1161         state()->hasClipping = op != Qt::NoClip || d->use_system_clip;
    1162     }
    1163 
    1164     if (state()->hasClipping && state()->clipRegion.rects().size() == 1)
    1165         state()->fastClip = state()->clipRegion.rects().at(0);
     2164        if (q->paintDevice()->devType() == QInternal::Widget && currentClipWidget) {
     2165            QWidgetPrivate *widgetPrivate = qt_widget_private(currentClipWidget->window());
     2166            useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter;
     2167        } else {
     2168            useSystemClip = true;
     2169        }
     2170    }
     2171
     2172    q->state()->clipTestEnabled = false;
     2173    q->state()->needsClipBufferClear = true;
     2174
     2175    q->state()->currentClip = 1;
     2176    maxClip = 1;
     2177
     2178    q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height);
     2179    updateClipScissorTest();
     2180
     2181    if (systemClip.rectCount() == 1) {
     2182        if (systemClip.boundingRect() == QRect(0, 0, width, height))
     2183            useSystemClip = false;
     2184#ifndef QT_GL_NO_SCISSOR_TEST
     2185        // scissoring takes care of the system clip
     2186        return;
     2187#endif
     2188    }
     2189
     2190    if (useSystemClip) {
     2191        clearClip(0);
     2192
     2193        QPainterPath path;
     2194        path.addRegion(systemClip);
     2195
     2196        q->state()->currentClip = 0;
     2197        writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1);
     2198        q->state()->currentClip = 1;
     2199        q->state()->clipTestEnabled = true;
     2200    }
     2201}
     2202
     2203void QGL2PaintEngineEx::setState(QPainterState *new_state)
     2204{
     2205    //     qDebug("QGL2PaintEngineEx::setState()");
     2206
     2207    Q_D(QGL2PaintEngineEx);
     2208
     2209    QOpenGL2PaintEngineState *s = static_cast<QOpenGL2PaintEngineState *>(new_state);
     2210    QOpenGL2PaintEngineState *old_state = state();
     2211
     2212    QPaintEngineEx::setState(s);
     2213
     2214    if (s->isNew) {
     2215        // Newly created state object.  The call to setState()
     2216        // will either be followed by a call to begin(), or we are
     2217        // setting the state as part of a save().
     2218        s->isNew = false;
     2219        return;
     2220    }
     2221
     2222    // Setting the state as part of a restore().
     2223
     2224    if (old_state == s || old_state->renderHintsChanged)
     2225        renderHintsChanged();
     2226
     2227    if (old_state == s || old_state->matrixChanged) {
     2228        d->matrixDirty = true;
     2229        d->simpleShaderMatrixUniformDirty = true;
     2230        d->shaderMatrixUniformDirty = true;
     2231    }
     2232
     2233    if (old_state == s || old_state->compositionModeChanged)
     2234        d->compositionModeDirty = true;
     2235
     2236    if (old_state == s || old_state->opacityChanged)
     2237        d->opacityUniformDirty = true;
     2238
     2239    if (old_state == s || old_state->clipChanged) {
     2240        if (old_state && old_state != s && old_state->canRestoreClip) {
     2241            d->updateClipScissorTest();
     2242            glDepthFunc(GL_LEQUAL);
     2243        } else {
     2244            d->regenerateClip();
     2245        }
     2246    }
     2247}
     2248
     2249QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
     2250{
     2251    if (orig)
     2252        const_cast<QGL2PaintEngineEx *>(this)->ensureActive();
     2253
     2254    QOpenGL2PaintEngineState *s;
     2255    if (!orig)
     2256        s = new QOpenGL2PaintEngineState();
    11662257    else
    1167         state()->fastClip = QRect();
    1168 
    1169     d->updateDepthClip();
    1170 }
    1171 
    1172 
    1173 void QGL2PaintEngineExPrivate::updateDepthClip()
    1174 {
    1175 //     qDebug("QGL2PaintEngineExPrivate::updateDepthClip()");
    1176 
    1177     Q_Q(QGL2PaintEngineEx);
    1178 
    1179     glDisable(GL_DEPTH_TEST);
    1180     glDisable(GL_SCISSOR_TEST);
    1181 
    1182     if (!q->state()->hasClipping)
    1183         return;
    1184 
    1185     QRect fastClip;
    1186     if (q->state()->clipEnabled) {
    1187         fastClip = q->state()->fastClip;
    1188     } else if (use_system_clip && q->systemClip().rects().count() == 1) {
    1189         fastClip = q->systemClip().rects().at(0);
    1190     }
    1191 
    1192     if (!fastClip.isEmpty()) {
    1193         glEnable(GL_SCISSOR_TEST);
    1194 
    1195         const int left = fastClip.left();
    1196         const int width = fastClip.width();
    1197         const int bottom = height - (fastClip.bottom() + 1);
    1198         const int height = fastClip.height();
    1199 
    1200         glScissor(left, bottom, width, height);
    1201         return;
    1202     }
    1203 
    1204     glClearDepthf(0x0);
    1205     glDepthMask(true);
    1206     glClear(GL_DEPTH_BUFFER_BIT);
    1207     glClearDepthf(0x1);
    1208 
    1209     const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects();
    1210     glEnable(GL_SCISSOR_TEST);
    1211     for (int i = 0; i < rects.size(); ++i) {
    1212         QRect rect = rects.at(i);
    1213 
    1214         const int left = rect.left();
    1215         const int width = rect.width();
    1216         const int bottom = height - (rect.bottom() + 1);
    1217         const int height = rect.height();
    1218 
    1219         glScissor(left, bottom, width, height);
    1220 
    1221         glClear(GL_DEPTH_BUFFER_BIT);
    1222     }
    1223     glDisable(GL_SCISSOR_TEST);
    1224 
    1225     glDepthMask(false);
    1226     glDepthFunc(GL_LEQUAL);
    1227     glEnable(GL_DEPTH_TEST);
    1228 }
    1229 
    1230 
    1231 
    1232 void QGL2PaintEngineEx::setState(QPainterState *s)
    1233 {
    1234 //     qDebug("QGL2PaintEngineEx::setState()");
    1235 
    1236     Q_D(QGL2PaintEngineEx);
    1237     QPaintEngineEx::setState(s);
    1238 
    1239     d->updateDepthClip();
    1240 
    1241     d->matrixDirty = true;
    1242     d->compositionModeDirty = true;
    1243     d->brushTextureDirty = true;
    1244     d->brushUniformsDirty = true;
    1245     d->simpleShaderMatrixUniformDirty = true;
    1246     d->brushShaderMatrixUniformDirty = true;
    1247     d->imageShaderMatrixUniformDirty = true;
    1248     d->textShaderMatrixUniformDirty = true;
    1249 }
    1250 
    1251 QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
    1252 {
    1253     QOpenGLPaintEngineState *s;
    1254     if (!orig)
    1255         s = new QOpenGLPaintEngineState();
    1256     else
    1257         s = new QOpenGLPaintEngineState(*static_cast<QOpenGLPaintEngineState *>(orig));
     2258        s = new QOpenGL2PaintEngineState(*static_cast<QOpenGL2PaintEngineState *>(orig));
     2259
     2260    s->matrixChanged = false;
     2261    s->compositionModeChanged = false;
     2262    s->opacityChanged = false;
     2263    s->renderHintsChanged = false;
     2264    s->clipChanged = false;
    12582265
    12592266    return s;
    12602267}
    12612268
    1262 QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other)
     2269QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other)
    12632270    : QPainterState(other)
    12642271{
    1265     clipRegion = other.clipRegion;
    1266     hasClipping = other.hasClipping;
    1267     fastClip = other.fastClip;
    1268 }
    1269 
    1270 QOpenGLPaintEngineState::QOpenGLPaintEngineState()
    1271 {
    1272     hasClipping = false;
    1273 }
    1274 
    1275 QOpenGLPaintEngineState::~QOpenGLPaintEngineState()
    1276 {
    1277 }
    1278 
     2272    isNew = true;
     2273    needsClipBufferClear = other.needsClipBufferClear;
     2274    clipTestEnabled = other.clipTestEnabled;
     2275    currentClip = other.currentClip;
     2276    canRestoreClip = other.canRestoreClip;
     2277    rectangleClip = other.rectangleClip;
     2278}
     2279
     2280QOpenGL2PaintEngineState::QOpenGL2PaintEngineState()
     2281{
     2282    isNew = true;
     2283    needsClipBufferClear = true;
     2284    clipTestEnabled = false;
     2285    canRestoreClip = true;
     2286}
     2287
     2288QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState()
     2289{
     2290}
     2291
     2292QT_END_NAMESPACE
     2293
     2294#include "qpaintengineex_opengl2.moc"
  • trunk/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5454//
    5555
     56#include <QDebug>
     57
    5658#include <private/qpaintengineex_p.h>
     59#include <private/qglengineshadermanager_p.h>
     60#include <private/qgl2pexvertexarray_p.h>
     61#include <private/qglpaintdevice_p.h>
     62#include <private/qglpixmapfilter_p.h>
     63#include <private/qfontengine_p.h>
     64#include <private/qdatabuffer_p.h>
     65#include <private/qtriangulatingstroker_p.h>
     66
     67enum EngineMode {
     68    ImageDrawingMode,
     69    TextDrawingMode,
     70    BrushDrawingMode,
     71    ImageArrayDrawingMode
     72};
     73
     74QT_BEGIN_NAMESPACE
    5775
    5876class QGL2PaintEngineExPrivate;
    5977
    6078
    61 class QOpenGLPaintEngineState : public QPainterState
     79class QOpenGL2PaintEngineState : public QPainterState
    6280{
    6381public:
    64     QOpenGLPaintEngineState(QOpenGLPaintEngineState &other);
    65     QOpenGLPaintEngineState();
    66     ~QOpenGLPaintEngineState();
    67 
    68     QRegion clipRegion;
    69     bool hasClipping;
    70     QRect fastClip;
    71 };
    72 
    73 
    74 class QGL2PaintEngineEx : public QPaintEngineEx
     82    QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other);
     83    QOpenGL2PaintEngineState();
     84    ~QOpenGL2PaintEngineState();
     85
     86    uint isNew : 1;
     87    uint needsClipBufferClear : 1;
     88    uint clipTestEnabled : 1;
     89    uint canRestoreClip : 1;
     90    uint matrixChanged : 1;
     91    uint compositionModeChanged : 1;
     92    uint opacityChanged : 1;
     93    uint renderHintsChanged : 1;
     94    uint clipChanged : 1;
     95    uint currentClip : 8;
     96
     97    QRect rectangleClip;
     98};
     99
     100class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
    75101{
    76102    Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
     
    80106
    81107    bool begin(QPaintDevice *device);
     108    void ensureActive();
    82109    bool end();
    83 
    84     virtual void fill(const QVectorPath &path, const QBrush &brush);
    85     virtual void stroke(const QVectorPath &path, const QPen &pen);
    86     virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
    87110
    88111    virtual void clipEnabledChanged();
     
    95118    virtual void transformChanged();
    96119
    97 
     120    virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
    98121    virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
    99 
     122    virtual void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
    100123    virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
    101124                           Qt::ImageConversionFlags flags = Qt::AutoColor);
    102125    virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
    103     void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
    104 
    105     Type type() const { return OpenGL; }
    106 
    107 
    108     // State stuff is just for clipping and ripped off from QGLPaintEngine
    109     void setState(QPainterState *s);
    110     QPainterState *createState(QPainterState *orig) const;
    111     inline QOpenGLPaintEngineState *state() {
    112         return static_cast<QOpenGLPaintEngineState *>(QPaintEngineEx::state());
    113     }
    114     inline const QOpenGLPaintEngineState *state() const {
    115         return static_cast<const QOpenGLPaintEngineState *>(QPaintEngineEx::state());
    116     }
    117     void updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op);
     126    virtual void fill(const QVectorPath &path, const QBrush &brush);
     127    virtual void stroke(const QVectorPath &path, const QPen &pen);
     128    virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
     129
     130
     131    Type type() const { return OpenGL2; }
     132
     133    virtual void setState(QPainterState *s);
     134    virtual QPainterState *createState(QPainterState *orig) const;
     135    inline QOpenGL2PaintEngineState *state() {
     136        return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
     137    }
     138    inline const QOpenGL2PaintEngineState *state() const {
     139        return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
     140    }
     141
     142    void beginNativePainting();
     143    void endNativePainting();
     144
     145    QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype);
     146
     147    void setRenderTextActive(bool);
    118148
    119149private:
     
    122152
    123153
     154class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
     155{
     156    Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
     157public:
     158    enum StencilFillMode {
     159        OddEvenFillMode,
     160        WindingFillMode,
     161        TriStripStrokeFillMode
     162    };
     163
     164    QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
     165            q(q_ptr),
     166            shaderManager(0),
     167            width(0), height(0),
     168            ctx(0),
     169            useSystemClip(true),
     170            snapToPixelGrid(false),
     171            addOffset(false),
     172            inverseScale(1)
     173    { }
     174
     175    ~QGL2PaintEngineExPrivate();
     176
     177    void updateBrushTexture();
     178    void updateBrushUniforms();
     179    void updateMatrix();
     180    void updateCompositionMode();
     181    void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1);
     182
     183    void resetGLState();
     184
     185    // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
     186    // however writeClip can also be thought of as en entry point as it does similar things.
     187    void fill(const QVectorPath &path);
     188    void stroke(const QVectorPath &path, const QPen &pen);
     189    void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
     190    void drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints);
     191    void drawCachedGlyphs(const QPointF &p, QFontEngineGlyphCache::Type glyphType, const QTextItemInt &ti);
     192
     193    // draws whatever is in the vertex array:
     194    void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
     195    void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
     196        drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
     197    }
     198
     199    // Composites the bounding rect onto dest buffer:
     200    void composite(const QGLRect& boundingRect);
     201
     202    // Calls drawVertexArrays to render into stencil buffer:
     203    void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode);
     204    void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) {
     205        fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
     206                                   vertexArray.boundingRect(),
     207                                   useWindingFill ? WindingFillMode : OddEvenFillMode);
     208    }
     209
     210    void setBrush(const QBrush& brush);
     211    void transferMode(EngineMode newMode);
     212    bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
     213    inline void useSimpleShader();
     214    inline GLuint location(const QGLEngineShaderManager::Uniform uniform) {
     215        return shaderManager->getUniformLocation(uniform);
     216    }
     217
     218    void clearClip(uint value);
     219    void writeClip(const QVectorPath &path, uint value);
     220    void resetClipIfNeeded();
     221
     222    void updateClipScissorTest();
     223    void setScissor(const QRect &rect);
     224    void regenerateClip();
     225    void systemStateChanged();
     226
     227    static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
     228    static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
     229    static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
     230
     231
     232    QGL2PaintEngineEx* q;
     233    QGLEngineShaderManager* shaderManager;
     234    QGLPaintDevice* device;
     235    int width, height;
     236    QGLContext *ctx;
     237    EngineMode mode;
     238    QFontEngineGlyphCache::Type glyphCacheType;
     239
     240    // Dirty flags
     241    bool matrixDirty; // Implies matrix uniforms are also dirty
     242    bool compositionModeDirty;
     243    bool brushTextureDirty;
     244    bool brushUniformsDirty;
     245    bool simpleShaderMatrixUniformDirty;
     246    bool shaderMatrixUniformDirty;
     247    bool opacityUniformDirty;
     248
     249    bool stencilClean; // Has the stencil not been used for clipping so far?
     250    bool useSystemClip;
     251    QRegion dirtyStencilRegion;
     252    QRect currentScissorBounds;
     253    uint maxClip;
     254
     255    QBrush currentBrush; // May not be the state's brush!
     256    const QBrush noBrush;
     257
     258    QGL2PEXVertexArray vertexCoordinateArray;
     259    QGL2PEXVertexArray textureCoordinateArray;
     260    QDataBuffer<GLfloat> opacityArray;
     261    GLfloat staticVertexCoordinateArray[8];
     262    GLfloat staticTextureCoordinateArray[8];
     263
     264    bool snapToPixelGrid;
     265    bool addOffset; // When enabled, adds a 0.49,0.49 offset to matrix in updateMatrix
     266    GLfloat pmvMatrix[3][3];
     267    GLfloat inverseScale;
     268
     269    GLuint lastTextureUsed;
     270
     271    bool needsSync;
     272    bool multisamplingAlwaysEnabled;
     273
     274    GLfloat depthRange[2];
     275
     276    float textureInvertedY;
     277
     278    QTriangulatingStroker stroker;
     279    QDashedStrokeProcessor dasher;
     280
     281    QScopedPointer<QPixmapFilter> convolutionFilter;
     282    QScopedPointer<QPixmapFilter> colorizeFilter;
     283    QScopedPointer<QPixmapFilter> blurFilter;
     284    QScopedPointer<QPixmapFilter> dropShadowFilter;
     285
     286    QSet<QVectorPath::CacheEntry *> pathCaches;
     287    QVector<GLuint> unusedVBOSToClean;
     288};
     289
     290QT_END_NAMESPACE
    124291
    125292#endif
  • trunk/src/opengl/opengl.pro

    r2 r561  
    1414contains(QT_CONFIG, opengl):CONFIG += opengl
    1515contains(QT_CONFIG, opengles1):CONFIG += opengles1
     16contains(QT_CONFIG, opengles1cl):CONFIG += opengles1cl
    1617contains(QT_CONFIG, opengles2):CONFIG += opengles2
    17 
    18 !contains(QT_CONFIG, opengles2) {
    19     HEADERS += qgraphicssystem_gl_p.h qwindowsurface_gl_p.h qpixmapdata_gl_p.h
    20     SOURCES += qgraphicssystem_gl.cpp qwindowsurface_gl.cpp qpixmapdata_gl.cpp
    21 }
     18contains(QT_CONFIG, egl):CONFIG += egl
    2219
    2320HEADERS += qgl.h \
     
    2522           qglcolormap.h \
    2623           qglpixelbuffer.h \
     24           qglpixelbuffer_p.h \
    2725           qglframebufferobject.h  \
     26           qglframebufferobject_p.h  \
     27           qglextensions_p.h \
     28           qglpaintdevice_p.h \
     29
    2830
    2931SOURCES += qgl.cpp \
     
    3234           qglframebufferobject.cpp \
    3335           qglextensions.cpp \
     36           qglpaintdevice.cpp \
     37
    3438
    3539!contains(QT_CONFIG, opengles2) {
    36     HEADERS += qpaintengine_opengl_p.h qglpixmapfilter_p.h
    37     SOURCES += qpaintengine_opengl.cpp qglpixmapfilter.cpp
     40    HEADERS += qpaintengine_opengl_p.h
     41    SOURCES += qpaintengine_opengl.cpp
    3842}
    3943
    40 contains(QT_CONFIG, opengles2) {
    41     SOURCES +=  gl2paintengineex/qglgradientcache.cpp \
    42                 gl2paintengineex/qglpexshadermanager.cpp \
    43                 gl2paintengineex/qglshader.cpp \
     44!contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles1cl) {
     45    HEADERS +=  qglshaderprogram.h \
     46                qglpixmapfilter_p.h  \
     47                qgraphicsshadereffect_p.h \
     48                qgraphicssystem_gl_p.h \
     49                qwindowsurface_gl_p.h \
     50                qpixmapdata_gl_p.h \
     51                gl2paintengineex/qglgradientcache_p.h \
     52                gl2paintengineex/qglengineshadermanager_p.h \
     53                gl2paintengineex/qgl2pexvertexarray_p.h \
     54                gl2paintengineex/qpaintengineex_opengl2_p.h \
     55                gl2paintengineex/qglengineshadersource_p.h \
     56                gl2paintengineex/qglcustomshaderstage_p.h \
     57                gl2paintengineex/qtriangulatingstroker_p.h
     58
     59    SOURCES +=  qglshaderprogram.cpp \
     60                qglpixmapfilter.cpp \
     61                qgraphicsshadereffect.cpp \
     62                qgraphicssystem_gl.cpp \
     63                qwindowsurface_gl.cpp \
     64                qpixmapdata_gl.cpp \
     65                gl2paintengineex/qglgradientcache.cpp \
     66                gl2paintengineex/qglengineshadermanager.cpp \
    4467                gl2paintengineex/qgl2pexvertexarray.cpp \
    45                 gl2paintengineex/qpaintengineex_opengl2.cpp
     68                gl2paintengineex/qpaintengineex_opengl2.cpp \
     69                gl2paintengineex/qglcustomshaderstage.cpp \
     70                gl2paintengineex/qtriangulatingstroker.cpp
    4671
    47     HEADERS +=  gl2paintengineex/qglgradientcache_p.h \
    48                 gl2paintengineex/qglpexshadermanager_p.h \
    49                 gl2paintengineex/qglshader_p.h \
    50                 gl2paintengineex/qgl2pexvertexarray_p.h \
    51                 gl2paintengineex/qpaintengineex_opengl2_p.h
    5272}
    53 
    5473
    5574x11 {
     
    5877                    qglpixelbuffer_egl.cpp \
    5978                    qgl_egl.cpp \
    60                     qegl.cpp \
    61                     qegl_x11egl.cpp
     79                    qpixmapdata_x11gl_egl.cpp \
     80                    qwindowsurface_x11gl.cpp
    6281
    63         HEADERS +=  qegl_p.h \
    64                     qgl_egl_p.h
     82        HEADERS +=  qgl_egl_p.h \
     83                    qpixmapdata_x11gl_p.h \
     84                    qwindowsurface_x11gl_p.h
    6585
    6686    } else {
     
    7090
    7191    contains(QT_CONFIG, fontconfig) {
     92        contains(QT_CONFIG, system-freetype) {
     93            embedded:CONFIG += opentype
     94            # pull in the proper freetype2 include directory
    7295            include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri)
     96            LIBS_PRIVATE += -lfreetype
     97        } else {
     98            ### Note: how does this compile with a non-system freetype?
     99            # This probably does not compile
     100        }
    73101    } else {
    74102        DEFINES *= QT_NO_FREETYPE
    75103    }
     104
     105    LIBS_PRIVATE += $$QMAKE_LIBS_DYNLOAD
    76106}
    77107
     
    79109    OBJECTIVE_SOURCES += qgl_mac.mm \
    80110                         qglpixelbuffer_mac.mm
    81     LIBS += -framework AppKit
     111    LIBS_PRIVATE += -framework AppKit -framework Carbon
    82112}
    83113win32:!wince*: {
     
    88118    SOURCES += qgl_wince.cpp \
    89119               qglpixelbuffer_egl.cpp \
    90                qgl_egl.cpp \
    91                qegl.cpp \
    92                qegl_wince.cpp
     120               qgl_egl.cpp
    93121
    94122    HEADERS += qgl_cl_p.h \
    95123               qgl_egl_p.h \
    96                qegl_p.h
    97124}
    98125
    99126embedded {
    100127    SOURCES += qgl_qws.cpp \
    101                qglpaintdevice_qws.cpp \
    102128               qglpixelbuffer_egl.cpp \
    103129               qglscreen_qws.cpp \
    104130               qglwindowsurface_qws.cpp \
    105                qegl.cpp \
    106                qegl_qws.cpp \
    107131               qgl_egl.cpp
    108132
    109     HEADERS += qglpaintdevice_qws_p.h \
    110                qglscreen_qws.h \
     133    HEADERS += qglscreen_qws.h \
    111134               qglwindowsurface_qws_p.h \
    112                qgl_egl_p.h \
    113                qegl_p.h
     135               qgl_egl_p.h
    114136
    115137    contains(QT_CONFIG, fontconfig) {
     
    121143
    122144INCLUDEPATH += ../3rdparty/harfbuzz/src
    123 
    124 wince*: {
    125     contains(QT_CONFIG,opengles1) {
    126         QMAKE_LIBS += "libGLES_CM.lib"
    127     }
    128     contains(QT_CONFIG,opengles1cl) {
    129         QMAKE_LIBS += "libGLES_CL.lib"
    130     }
    131     contains(QT_CONFIG,opengles2) {
    132         QMAKE_LIBS += "libGLESv2.lib"
    133     }
    134 
    135 } else {
    136     QMAKE_LIBS += $$QMAKE_LIBS_OPENGL
    137 }
  • trunk/src/opengl/qgl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6060#endif
    6161
     62#include <qdatetime.h>
     63
    6264#include <stdlib.h> // malloc
    6365
     
    6668#include "qgl_p.h"
    6769
    68 #if defined(QT_OPENGL_ES_2)
     70#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
    6971#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
    70 #else
     72#endif
     73
     74#ifndef QT_OPENGL_ES_2
    7175#include <private/qpaintengine_opengl_p.h>
    7276#endif
     77
     78#ifdef Q_WS_QWS
     79#include <private/qglwindowsurface_qws_p.h>
     80#endif
     81
     82#include <qglpixelbuffer.h>
     83#include <qglframebufferobject.h>
    7384
    7485#include <private/qimage_p.h>
    7586#include <private/qpixmapdata_p.h>
    7687#include <private/qpixmapdata_gl_p.h>
     88#include <private/qglpixelbuffer_p.h>
     89#include <private/qwindowsurface_gl_p.h>
     90#include <private/qimagepixmapcleanuphooks_p.h>
    7791#include "qcolormap.h"
    78 #include "qcache.h"
    7992#include "qfile.h"
    8093#include "qlibrary.h"
     
    92105#endif
    93106
    94 QThreadStorage<QGLThreadContext *> qgl_context_storage;
     107struct QGLThreadContext {
     108    QGLContext *context;
     109};
     110
     111static QThreadStorage<QGLThreadContext *> qgl_context_storage;
    95112
    96113Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
     
    111128bool QGLExtensions::nvidiaFboNeedsFinish = false;
    112129
    113 #ifndef APIENTRY
    114 # define APIENTRY
    115 #endif
    116 typedef void (APIENTRY *pfn_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
    117                                                         GLsizei, GLint, GLsizei, const GLvoid *);
    118 static pfn_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB = 0;
    119 
    120 
    121 #ifndef APIENTRY
    122 #define APIENTRY
    123 #endif
    124 
    125130Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
    126131QGLSignalProxy *QGLSignalProxy::instance()
     
    129134}
    130135
     136
     137class QGLEngineSelector
     138{
     139public:
     140    QGLEngineSelector() : engineType(QPaintEngine::MaxUser)
     141    {
     142    }
     143
     144    void setPreferredPaintEngine(QPaintEngine::Type type) {
     145        if (type == QPaintEngine::OpenGL || type == QPaintEngine::OpenGL2)
     146            engineType = type;
     147    }
     148
     149    QPaintEngine::Type preferredPaintEngine() {
     150#ifdef Q_WS_MAC
     151        // The ATI X1600 driver for Mac OS X does not support return
     152        // values from functions in GLSL. Since working around this in
     153        // the GL2 engine would require a big, ugly rewrite, we're
     154        // falling back to the GL 1 engine..
     155        static bool mac_x1600_check_done = false;
     156        if (!mac_x1600_check_done) {
     157            QGLWidget *tmp = 0;
     158            if (!QGLContext::currentContext()) {
     159                tmp = new QGLWidget();
     160                tmp->makeCurrent();
     161            }
     162            if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
     163                engineType = QPaintEngine::OpenGL;
     164            if (tmp)
     165                delete tmp;
     166            mac_x1600_check_done = true;
     167        }
     168#endif
     169        if (engineType == QPaintEngine::MaxUser) {
     170            // No user-set engine - use the defaults
     171#if defined(QT_OPENGL_ES_2)
     172            engineType = QPaintEngine::OpenGL2;
     173#else
     174            // We can't do this in the constructor for this object because it
     175            // needs to be called *before* the QApplication constructor.
     176            // Also check for the FragmentShader extension in conjunction with
     177            // the 2.0 version flag, to cover the case where we export the display
     178            // from an old GL 1.1 server to a GL 2.x client. In that case we can't
     179            // use GL 2.0.
     180            if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
     181                && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
     182                && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
     183                engineType = QPaintEngine::OpenGL2;
     184            else
     185                engineType = QPaintEngine::OpenGL;
     186#endif
     187        }
     188        return engineType;
     189    }
     190
     191private:
     192    QPaintEngine::Type engineType;
     193};
     194
     195Q_GLOBAL_STATIC(QGLEngineSelector, qgl_engine_selector)
     196
     197
     198bool qt_gl_preferGL2Engine()
     199{
     200    return qgl_engine_selector()->preferredPaintEngine() == QPaintEngine::OpenGL2;
     201}
     202
     203
    131204/*!
    132205    \namespace QGL
     206    \inmodule QtOpenGL
    133207
    134208    \brief The QGL namespace specifies miscellaneous identifiers used
    135209    in the Qt OpenGL module.
    136210
    137     \ingroup multimedia
     211    \ingroup painting-3D
    138212*/
    139213
     
    168242*/
    169243
     244/*!
     245   \fn void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
     246
     247   \since 4.6
     248
     249   Sets the preferred OpenGL paint engine that is used to draw onto
     250   QGLWidget, QGLPixelBuffer and QGLFramebufferObject targets with QPainter
     251   in Qt.
     252
     253   The \a engineType parameter specifies which of the GL engines to
     254   use. Only \c QPaintEngine::OpenGL and \c QPaintEngine::OpenGL2 are
     255   valid parameters to this function. All other values are ignored.
     256
     257   By default, the \c QPaintEngine::OpenGL2 engine is used if GL/GLES
     258   version 2.0 is available, otherwise \c QPaintEngine::OpenGL is
     259   used.
     260
     261   \warning This function must be called before the QApplication
     262   constructor is called.
     263*/
     264void QGL::setPreferredPaintEngine(QPaintEngine::Type engineType)
     265{
     266    qgl_engine_selector()->setPreferredPaintEngine(engineType);
     267}
     268
     269
    170270/*****************************************************************************
    171271  QGLFormat implementation
     
    178278    rendering context.
    179279
    180     \ingroup multimedia
     280    \ingroup painting-3D
    181281
    182282    A display format has several characteristics:
     
    191291    \i \link setDirectRendering() Direct rendering.\endlink
    192292    \i \link setOverlay() Presence of an overlay.\endlink
    193     \i \link setPlane() The plane of an overlay format.\endlink
     293    \i \link setPlane() Plane of an overlay.\endlink
    194294    \i \link setSampleBuffers() Multisample buffers.\endlink
    195295    \endlist
    196296
    197     You can also specify preferred bit depths for the depth buffer,
    198     alpha buffer, accumulation buffer and the stencil buffer with the
    199     functions: setDepthBufferSize(), setAlphaBufferSize(),
     297    You can also specify preferred bit depths for the color buffer,
     298    depth buffer, alpha buffer, accumulation buffer and the stencil
     299    buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
     300    setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
    200301    setAccumBufferSize() and setStencilBufferSize().
    201302
     
    237338    \sa QGLContext, QGLWidget
    238339*/
     340
     341#ifndef QT_OPENGL_ES
    239342
    240343static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
     
    280383}
    281384
    282 /*!
    283     Constructs a QGLFormat object with the factory default settings:
     385#endif // !QT_OPENGL_ES
     386
     387/*!
     388    Constructs a QGLFormat object with the following default settings:
    284389    \list
    285390    \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
     
    288393    \i \link setAlpha() Alpha channel:\endlink Disabled.
    289394    \i \link setAccum() Accumulator buffer:\endlink Disabled.
    290     \i \link setStencil() Stencil buffer:\endlink Disabled.
     395    \i \link setStencil() Stencil buffer:\endlink Enabled.
    291396    \i \link setStereo() Stereo:\endlink Disabled.
    292397    \i \link setDirectRendering() Direct rendering:\endlink Enabled.
     
    304409
    305410/*!
    306     Creates a QGLFormat object that is a copy of the current \link
    307     defaultFormat() application default format\endlink.
    308 
    309     If \a options is not 0, this copy is modified by these format
    310     options. The \a options parameter should be \c FormatOption values
    311     OR'ed together.
     411    Creates a QGLFormat object that is a copy of the current
     412    defaultFormat().
     413
     414    If \a options is not 0, the default format is modified by the
     415    specified format options. The \a options parameter should be
     416    QGL::FormatOption values OR'ed together.
    312417
    313418    This constructor makes it easy to specify a certain desired format
     
    315420    \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3
    316421
    317     Note that there are \c FormatOption values to turn format settings
    318     both on and off, e.g. \c DepthBuffer and \c NoDepthBuffer,
    319     \c DirectRendering and \c IndirectRendering, etc.
     422    Note that there are QGL::FormatOption values to turn format settings
     423    both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
     424    QGL::DirectRendering and QGL::IndirectRendering, etc.
    320425
    321426    The \a plane parameter defaults to 0 and is the plane which this
     
    323428    supports overlay/underlay rendering planes.
    324429
    325     \sa defaultFormat(), setOption()
     430    \sa defaultFormat(), setOption(), setPlane()
    326431*/
    327432
     
    337442
    338443/*!
     444    \internal
     445*/
     446void QGLFormat::detach()
     447{
     448    if (d->ref != 1) {
     449        QGLFormatPrivate *newd = new QGLFormatPrivate(d);
     450        if (!d->ref.deref())
     451            delete d;
     452        d = newd;
     453    }
     454}
     455
     456/*!
    339457    Constructs a copy of \a other.
    340458*/
     
    342460QGLFormat::QGLFormat(const QGLFormat &other)
    343461{
    344     d = new QGLFormatPrivate;
    345     *d = *other.d;
     462    d = other.d;
     463    d->ref.ref();
    346464}
    347465
     
    352470QGLFormat &QGLFormat::operator=(const QGLFormat &other)
    353471{
    354     *d = *other.d;
     472    if (d != other.d) {
     473        other.d->ref.ref();
     474        if (!d->ref.deref())
     475            delete d;
     476        d = other.d;
     477    }
    355478    return *this;
    356479}
     
    361484QGLFormat::~QGLFormat()
    362485{
    363     delete d;
     486    if (!d->ref.deref())
     487        delete d;
    364488}
    365489
     
    515639
    516640    Returns true if the stencil buffer is enabled; otherwise returns
    517     false. The stencil buffer is disabled by default.
     641    false. The stencil buffer is enabled by default.
    518642
    519643    \sa setStencil(), setStencilBufferSize()
     
    524648    disables the stencil buffer.
    525649
    526     The stencil buffer is disabled by default.
     650    The stencil buffer is enabled by default.
    527651
    528652    The stencil buffer masks certain parts of the drawing area so that
     
    637761void QGLFormat::setSamples(int numSamples)
    638762{
     763    detach();
    639764    if (numSamples < 0) {
    640765        qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
     
    664789void QGLFormat::setSwapInterval(int interval)
    665790{
     791    detach();
    666792    d->swapInterval = interval;
    667793}
     
    709835    formats is 1, which is the first overlay plane.
    710836
    711     \sa setPlane()
     837    \sa setPlane(), defaultOverlayFormat()
    712838*/
    713839int QGLFormat::plane() const
     
    731857void QGLFormat::setPlane(int plane)
    732858{
     859    detach();
    733860    d->pln = plane;
    734861}
     
    742869void QGLFormat::setOption(QGL::FormatOptions opt)
    743870{
     871    detach();
    744872    if (opt & 0xffff)
    745873        d->opts |= opt;
     
    771899void QGLFormat::setDepthBufferSize(int size)
    772900{
     901    detach();
    773902    if (size < 0) {
    774903        qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
     
    797926void QGLFormat::setRedBufferSize(int size)
    798927{
     928    detach();
    799929    if (size < 0) {
    800930        qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
     
    825955void QGLFormat::setGreenBufferSize(int size)
    826956{
     957    detach();
    827958    if (size < 0) {
    828959        qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
     
    853984void QGLFormat::setBlueBufferSize(int size)
    854985{
     986    detach();
    855987    if (size < 0) {
    856988        qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
     
    8801012void QGLFormat::setAlphaBufferSize(int size)
    8811013{
     1014    detach();
    8821015    if (size < 0) {
    8831016        qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
     
    9061039void QGLFormat::setAccumBufferSize(int size)
    9071040{
     1041    detach();
    9081042    if (size < 0) {
    9091043        qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
     
    9301064void QGLFormat::setStencilBufferSize(int size)
    9311065{
     1066    detach();
    9321067    if (size < 0) {
    9331068        qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
     
    11251260            return defaultVersionFlags;
    11261261        } else {
    1127             cachedDefault = true;
    11281262            if (!hasOpenGL())
    11291263                return defaultVersionFlags;
    11301264            dummy = new QGLWidget;
    11311265            dummy->makeCurrent(); // glGetString() needs a current context
     1266            cachedDefault = true;
    11321267        }
    11331268    }
     
    11491284
    11501285/*!
    1151     Returns the default QGLFormat for the application. All QGLWidgets
    1152     that are created use this format unless another format is
     1286    Returns the default QGLFormat for the application. All QGLWidget
     1287    objects that are created use this format unless another format is
    11531288    specified, e.g. when they are constructed.
    11541289
     
    11831318    Returns the default QGLFormat for overlay contexts.
    11841319
    1185     The factory default overlay format is:
     1320    The default overlay format is:
    11861321    \list
    11871322    \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
     
    11941329    \i \link setDirectRendering() Direct rendering:\endlink Enabled.
    11951330    \i \link setOverlay() Overlay:\endlink Disabled.
     1331    \i \link setSampleBuffers() Multisample buffers:\endlink Disabled.
    11961332    \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
    11971333    \endlist
     
    12361372
    12371373/*!
    1238     Returns true if all the options of the two QGLFormats are equal;
    1239     otherwise returns false.
     1374    Returns true if all the options of the two QGLFormat objects
     1375    \a a and \a b are equal; otherwise returns false.
     1376
     1377    \relates QGLFormat
    12401378*/
    12411379
     
    12441382    return (int) a.d->opts == (int) b.d->opts && a.d->pln == b.d->pln && a.d->alphaSize == b.d->alphaSize
    12451383        && a.d->accumSize == b.d->accumSize && a.d->stencilSize == b.d->stencilSize
    1246         && a.d->depthSize == b.d->depthSize;
    1247 }
    1248 
    1249 
    1250 /*!
    1251     Returns false if all the options of the two QGLFormats are equal;
    1252     otherwise returns true.
     1384        && a.d->depthSize == b.d->depthSize
     1385        && a.d->redSize == b.d->redSize
     1386        && a.d->greenSize == b.d->greenSize
     1387        && a.d->blueSize == b.d->blueSize
     1388        && a.d->numSamples == b.d->numSamples
     1389        && a.d->swapInterval == b.d->swapInterval;
     1390}
     1391
     1392
     1393/*!
     1394    Returns false if all the options of the two QGLFormat objects
     1395    \a a and \a b are equal; otherwise returns true.
     1396
     1397    \relates QGLFormat
    12531398*/
    12541399
     
    12611406  QGLContext implementation
    12621407 *****************************************************************************/
     1408
     1409QGLContextGroup::~QGLContextGroup()
     1410{
     1411    // Clear any remaining QGLSharedResourceGuard objects on the group.
     1412    QGLSharedResourceGuard *guard = m_guards;
     1413    while (guard != 0) {
     1414        guard->m_group = 0;
     1415        guard->m_id = 0;
     1416        guard = guard->m_next;
     1417    }
     1418}
     1419
     1420void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
     1421{
     1422    if (m_guards)
     1423        m_guards->m_prev = guard;
     1424    guard->m_next = m_guards;
     1425    guard->m_prev = 0;
     1426    m_guards = guard;
     1427}
     1428
     1429void QGLContextGroup::removeGuard(QGLSharedResourceGuard *guard)
     1430{
     1431    if (guard->m_next)
     1432        guard->m_next->m_prev = guard->m_prev;
     1433    if (guard->m_prev)
     1434        guard->m_prev->m_next = guard->m_next;
     1435    else
     1436        m_guards = guard->m_next;
     1437}
     1438
     1439QGLContextPrivate::~QGLContextPrivate()
     1440{
     1441    if (!group->m_refs.deref()) {
     1442        Q_ASSERT(group->context() == q_ptr);
     1443        delete group;
     1444    }
     1445}
     1446
    12631447void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
    12641448{
     
    12891473#if defined(QT_OPENGL_ES)
    12901474    eglContext = 0;
    1291 #endif
    1292     pbo = 0;
     1475    eglSurface = EGL_NO_SURFACE;
     1476#endif
     1477    fbo = 0;
    12931478    crWin = false;
    12941479    initDone = false;
    12951480    sharing = false;
    1296     clear_on_painter_begin = true;
    12971481    max_texture_size = -1;
    12981482    version_flags_cached = false;
    12991483    version_flags = QGLFormat::OpenGL_Version_None;
     1484    current_fbo = 0;
     1485    default_fbo = 0;
     1486    active_engine = 0;
    13001487}
    13011488
     
    13081495*/
    13091496
    1310 QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
    1311 {
    1312     QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
    1313     int w = size.width();
    1314     int h = size.height();
    1315     glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
     1497static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
     1498{
    13161499    if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
    13171500        // OpenGL gives RGBA; Qt wants ARGB
     
    13281511            // we shouldn't remove
    13291512            while (p < end) {
    1330                 *p = 0xFF000000 | (*p>>8);
     1513                *p = 0xff000000 | (*p>>8);
    13311514                ++p;
    13321515            }
     
    13341517    } else {
    13351518        // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
    1336         img = img.rgbSwapped();
    1337     }
    1338     return img.mirrored();
     1519        for (int y = 0; y < h; y++) {
     1520            uint *q = (uint*)img.scanLine(y);
     1521            for (int x=0; x < w; ++x) {
     1522                const uint pixel = *q;
     1523                *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
     1524                q++;
     1525            }
     1526        }
     1527
     1528    }
     1529    img = img.mirrored();
     1530}
     1531
     1532QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
     1533{
     1534    QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
     1535    int w = size.width();
     1536    int h = size.height();
     1537    glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
     1538    convertFromGLImage(img, w, h, alpha_format, include_alpha);
     1539    return img;
     1540}
     1541
     1542QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
     1543{
     1544    QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
     1545    int w = size.width();
     1546    int h = size.height();
     1547#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     1548    //### glGetTexImage not in GL ES 2.0, need to do something else here!
     1549    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
     1550#endif
     1551    convertFromGLImage(img, w, h, alpha_format, include_alpha);
     1552    return img;
    13391553}
    13401554
     
    13531567}
    13541568
    1355 class QGLTexture {
    1356 public:
    1357     QGLTexture(const QGLContext *ctx, GLuint tx_id, GLenum tx_target, bool _clean = false)
    1358         : context(ctx), id(tx_id), target(tx_target), clean(_clean) {}
    1359     ~QGLTexture() {
    1360         if (clean) {
    1361             QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
    1362             QGLContext *ctx = const_cast<QGLContext *>(context);
    1363             bool switch_context = current && current != ctx && !qgl_share_reg()->checkSharing(current, ctx);
    1364             if (switch_context)
    1365                 ctx->makeCurrent();
    1366             glDeleteTextures(1, &id);
    1367             if (switch_context)
    1368                 current->makeCurrent();
    1369         }
    1370      }
    1371 
    1372     const QGLContext *context;
    1373     GLuint id;
    1374     GLenum target;
    1375     bool clean;
    1376 };
    1377 
    1378 typedef QCache<qint64, QGLTexture> QGLTextureCache;
    1379 static int qt_tex_cache_limit = 64*1024; // cache ~64 MB worth of textures - this is not accurate though
    1380 static QGLTextureCache *qt_tex_cache = 0;
    1381 
    13821569typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
    13831570typedef void (*_qt_image_cleanup_hook_64)(qint64);
     
    13851572extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
    13861573extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
     1574
     1575static QGLTextureCache *qt_gl_texture_cache = 0;
     1576
     1577QGLTextureCache::QGLTextureCache()
     1578    : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
     1579{
     1580    Q_ASSERT(qt_gl_texture_cache == 0);
     1581    qt_gl_texture_cache = this;
     1582
     1583    QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
     1584#ifdef Q_WS_X11
     1585    QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
     1586#endif
     1587    QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
     1588}
     1589
     1590QGLTextureCache::~QGLTextureCache()
     1591{
     1592    qt_gl_texture_cache = 0;
     1593
     1594    QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
     1595#ifdef Q_WS_X11
     1596    QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
     1597#endif
     1598    QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
     1599}
     1600
     1601void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
     1602{
     1603    if (m_cache.totalCost() + cost > m_cache.maxCost()) {
     1604        // the cache is full - make an attempt to remove something
     1605        const QList<qint64> keys = m_cache.keys();
     1606        int i = 0;
     1607        while (i < m_cache.count()
     1608               && (m_cache.totalCost() + cost > m_cache.maxCost())) {
     1609            QGLTexture *tex = m_cache.object(keys.at(i));
     1610            if (tex->context == ctx)
     1611                m_cache.remove(keys.at(i));
     1612            ++i;
     1613        }
     1614    }
     1615    m_cache.insert(key, texture, cost);
     1616}
     1617
     1618bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
     1619{
     1620    QList<qint64> keys = m_cache.keys();
     1621    for (int i = 0; i < keys.size(); ++i) {
     1622        QGLTexture *tex = m_cache.object(keys.at(i));
     1623        if (tex->id == textureId && tex->context == ctx) {
     1624            tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
     1625            m_cache.remove(keys.at(i));
     1626            return true;
     1627        }
     1628    }
     1629    return false;
     1630}
     1631
     1632void QGLTextureCache::removeContextTextures(QGLContext* ctx)
     1633{
     1634    QList<qint64> keys = m_cache.keys();
     1635    for (int i = 0; i < keys.size(); ++i) {
     1636        const qint64 &key = keys.at(i);
     1637        if (m_cache.object(key)->context == ctx)
     1638            m_cache.remove(key);
     1639    }
     1640}
     1641
     1642QGLTextureCache* QGLTextureCache::instance()
     1643{
     1644    if (!qt_gl_texture_cache)
     1645        qt_gl_texture_cache = new QGLTextureCache;
     1646
     1647    return qt_gl_texture_cache;
     1648}
     1649
     1650/*
     1651  a hook that removes textures from the cache when a pixmap/image
     1652  is deref'ed
     1653*/
     1654void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
     1655{
     1656    // ### remove when the GL texture cache becomes thread-safe
     1657    if (qApp->thread() != QThread::currentThread())
     1658        return;
     1659    QGLTexture *texture = instance()->getTexture(cacheKey);
     1660    if (texture && texture->options & QGLContext::MemoryManagedBindOption)
     1661        instance()->remove(cacheKey);
     1662}
     1663
     1664
     1665void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
     1666{
     1667    // ### remove when the GL texture cache becomes thread-safe
     1668    if (qApp->thread() == QThread::currentThread()) {
     1669        const qint64 cacheKey = pixmap->cacheKey();
     1670        QGLTexture *texture = instance()->getTexture(cacheKey);
     1671        if (texture && texture->options & QGLContext::MemoryManagedBindOption)
     1672            instance()->remove(cacheKey);
     1673    }
     1674}
     1675
     1676#if defined(Q_WS_X11)
     1677void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
     1678{
     1679    // Remove any bound textures first:
     1680    cleanupTextures(pixmap);
     1681
     1682    QPixmapData *pd = pixmap->data_ptr().data();
     1683    if (pd->classId() == QPixmapData::X11Class) {
     1684        Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
     1685        QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
     1686    }
     1687}
     1688#endif
     1689
     1690void QGLTextureCache::deleteIfEmpty()
     1691{
     1692    if (instance()->size() == 0)
     1693        delete instance();
     1694}
    13871695
    13881696// DDS format structure
     
    14221730#endif
    14231731
    1424 Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg);
     1732Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
    14251733Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
    14261734{
     
    14321740    \brief The QGLContext class encapsulates an OpenGL rendering context.
    14331741
    1434     \ingroup multimedia
     1742    \ingroup painting-3D
    14351743
    14361744    An OpenGL rendering context is a complete set of OpenGL state
     
    14571765*/
    14581766
     1767/*!
     1768    \enum QGLContext::BindOption
     1769    \since 4.6
     1770
     1771    A set of options to decide how to bind a texture using bindTexture().
     1772
     1773    \value NoBindOption Don't do anything, pass the texture straight
     1774    through.
     1775
     1776    \value InvertedYBindOption Specifies that the texture should be flipped
     1777    over the X axis so that the texture coordinate 0,0 corresponds to
     1778    the top left corner. Inverting the texture implies a deep copy
     1779    prior to upload.
     1780
     1781    \value MipmapBindOption Specifies that bindTexture() should try
     1782    to generate mipmaps.  If the GL implementation supports the \c
     1783    GL_SGIS_generate_mipmap extension, mipmaps will be automatically
     1784    generated for the texture. Mipmap generation is only supported for
     1785    the \c GL_TEXTURE_2D target.
     1786
     1787    \value PremultipliedAlphaBindOption Specifies that the image should be
     1788    uploaded with premultiplied alpha and does a conversion accordingly.
     1789
     1790    \value LinearFilteringBindOption Specifies that the texture filtering
     1791    should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
     1792    also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
     1793
     1794    \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
     1795    would mirror the image and automatically generate mipmaps. This
     1796    option helps preserve this default behavior.
     1797
     1798    \omitvalue CanFlipNativePixmapBindOption Used by x11 from pixmap to choose
     1799    wether or not it can bind the pixmap upside down or not.
     1800
     1801    \omitvalue MemoryManagedBindOption Used by paint engines to
     1802    indicate that the pixmap should be memory managed along side with
     1803    the pixmap/image that it stems from, e.g. installing destruction
     1804    hooks in them.
     1805
     1806    \omitvalue InternalBindOption
     1807*/
    14591808
    14601809/*!
     
    14771826
    14781827QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
    1479 {
    1480     d_ptr = new QGLContextPrivate(this);
     1828    : d_ptr(new QGLContextPrivate(this))
     1829{
    14811830    Q_D(QGLContext);
    14821831    d->init(device, format);
     
    15001849*/
    15011850QGLContext::QGLContext(const QGLFormat &format)
    1502 {
    1503     d_ptr = new QGLContextPrivate(this);
     1851    : d_ptr(new QGLContextPrivate(this))
     1852{
    15041853    Q_D(QGLContext);
    15051854    d->init(0, format);
     
    15121861QGLContext::~QGLContext()
    15131862{
    1514     Q_D(QGLContext);
    15151863    // remove any textures cached in this context
    1516     if (qt_tex_cache) {
    1517         QList<qint64> keys = qt_tex_cache->keys();
    1518         for (int i = 0; i < keys.size(); ++i) {
    1519             const qint64 &key = keys.at(i);
    1520             if (qt_tex_cache->object(key)->context == this)
    1521                 qt_tex_cache->remove(key);
    1522         }
    1523         // ### thread safety
    1524         if (qt_tex_cache->size() == 0) {
    1525             qt_pixmap_cleanup_hook_64 = 0;
    1526             qt_image_cleanup_hook_64 = 0;
    1527             delete qt_tex_cache;
    1528             qt_tex_cache = 0;
    1529         }
    1530     }
     1864    QGLTextureCache::instance()->removeContextTextures(this);
     1865    QGLTextureCache::deleteIfEmpty(); // ### thread safety
     1866
     1867    d_ptr->group->cleanupResources(this);
    15311868
    15321869    QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
    15331870    reset();
    1534     delete d;
    15351871}
    15361872
    15371873void QGLContextPrivate::cleanup()
    15381874{
    1539     Q_Q(QGLContext);
    1540     if (pbo) {
    1541         QGLContext *ctx = q;
    1542         glDeleteBuffersARB(1, &pbo);
    1543         pbo = 0;
    1544     }
    1545 }
    1546 
    1547 typedef QHash<QString, GLuint> QGLDDSCache;
    1548 Q_GLOBAL_STATIC(QGLDDSCache, qgl_dds_cache)
     1875}
    15491876
    15501877/*!
    15511878    \overload
    15521879
    1553     Reads the DirectDrawSurface (DDS) compressed file \a fileName and
    1554     generates a 2D GL texture from it.
    1555 
    1556     Only the DXT1, DXT3 and DXT5 DDS formats are supported.
    1557 
    1558     Note that this will only work if the implementation supports the
    1559     \c GL_ARB_texture_compression and \c GL_EXT_texture_compression_s3tc
    1560     extensions.
     1880    Reads the compressed texture file \a fileName and generates a 2D GL
     1881    texture from it.
     1882
     1883    This function can load DirectDrawSurface (DDS) textures in the
     1884    DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
     1885    and \c GL_EXT_texture_compression_s3tc extensions are supported.
     1886
     1887    Since 4.6.1, textures in the ETC1 format can be loaded if the
     1888    \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
     1889    and the ETC1 texture has been encapsulated in the PVR container format.
     1890    Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
     1891    if the \c GL_IMG_texture_compression_pvrtc extension is supported.
    15611892
    15621893    \sa deleteTexture()
     
    15651896GLuint QGLContext::bindTexture(const QString &fileName)
    15661897{
    1567     if (!qt_glCompressedTexImage2DARB) {
    1568         qWarning("QGLContext::bindTexture(): The GL implementation does not support texture"
    1569                  "compression extensions.");
    1570         return 0;
    1571     }
    1572 
    1573     QGLDDSCache::const_iterator it = qgl_dds_cache()->constFind(fileName);
    1574     if (it != qgl_dds_cache()->constEnd()) {
     1898    Q_D(QGLContext);
     1899    QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
     1900    QGLDDSCache::const_iterator it = dds_cache->constFind(fileName);
     1901    if (it != dds_cache->constEnd()) {
    15751902        glBindTexture(GL_TEXTURE_2D, it.value());
    15761903        return it.value();
    15771904    }
    15781905
    1579     QFile f(fileName);
    1580     f.open(QIODevice::ReadOnly);
    1581 
    1582     char tag[4];
    1583     f.read(&tag[0], 4);
    1584     if (strncmp(tag,"DDS ", 4) != 0) {
    1585         qWarning("QGLContext::bindTexture(): not a DDS image file.");
     1906    QGLTexture texture(this);
     1907    QSize size = texture.bindCompressedTexture(fileName);
     1908    if (!size.isValid())
    15861909        return 0;
    1587     }
    1588 
    1589     DDSFormat ddsHeader;
    1590     f.read((char *) &ddsHeader, sizeof(DDSFormat));
    1591 
    1592     if (!ddsHeader.dwLinearSize) {
    1593         qWarning("QGLContext::bindTexture() DDS image size is not valid.");
    1594         return 0;
    1595     }
    1596 
    1597     int factor = 4;
    1598     int bufferSize = 0;
    1599     int blockSize = 16;
    1600     GLenum format;
    1601 
    1602     switch(ddsHeader.ddsPixelFormat.dwFourCC) {
    1603     case FOURCC_DXT1:
    1604         format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
    1605         factor = 2;
    1606         blockSize = 8;
    1607         break;
    1608     case FOURCC_DXT3:
    1609         format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
    1610         break;
    1611     case FOURCC_DXT5:
    1612         format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
    1613         break;
    1614     default:
    1615         qWarning("QGLContext::bindTexture() DDS image format not supported.");
    1616         return 0;
    1617     }
    1618 
    1619     if (ddsHeader.dwMipMapCount > 1)
    1620         bufferSize = ddsHeader.dwLinearSize * factor;
    1621     else
    1622         bufferSize = ddsHeader.dwLinearSize;
    1623 
    1624     GLubyte *pixels = (GLubyte *) malloc(bufferSize*sizeof(GLubyte));
    1625     f.seek(ddsHeader.dwSize + 4);
    1626     f.read((char *) pixels, bufferSize);
    1627     f.close();
    1628 
    1629     GLuint tx_id;
    1630     glGenTextures(1, &tx_id);
    1631     glBindTexture(GL_TEXTURE_2D, tx_id);
    1632     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    1633     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    1634 
    1635     int size;
    1636     int offset = 0;
    1637     int w = ddsHeader.dwWidth;
    1638     int h = ddsHeader.dwHeight;
    1639 
    1640     // load mip-maps
    1641     for(int i = 0; i < (int) ddsHeader.dwMipMapCount; ++i) {
    1642         if (w == 0) w = 1;
    1643         if (h == 0) h = 1;
    1644 
    1645         size = ((w+3)/4) * ((h+3)/4) * blockSize;
    1646         qt_glCompressedTexImage2DARB(GL_TEXTURE_2D, i, format, w, h, 0,
    1647                                      size, pixels + offset);
    1648         offset += size;
    1649 
    1650         // half size for each mip-map level
    1651         w = w/2;
    1652         h = h/2;
    1653     }
    1654 
    1655     free(pixels);
    1656 
    1657     qgl_dds_cache()->insert(fileName, tx_id);
    1658     return tx_id;
    1659 }
    1660 
    1661 /*
    1662   a hook that removes textures from the cache when a pixmap/image
    1663   is deref'ed
    1664 */
    1665 static void qt_gl_clean_cache(qint64 cacheKey)
    1666 {
    1667     // ### remove when the GL texture cache becomes thread-safe
    1668     if (qApp->thread() != QThread::currentThread())
    1669         return;
    1670     if (qt_tex_cache) {
    1671         QGLTexture *texture = qt_tex_cache->object(cacheKey);
    1672         if (texture && texture->clean)
    1673             qt_tex_cache->remove(cacheKey);
    1674     }
     1910
     1911    dds_cache->insert(fileName, texture.id);
     1912    return texture.id;
     1913}
     1914
     1915static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
     1916{
     1917    if (texture_format == GL_BGRA) {
     1918        if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
     1919            return ((src_pixel << 24) & 0xff000000)
     1920                   | ((src_pixel >> 24) & 0x000000ff)
     1921                   | ((src_pixel << 8) & 0x00ff0000)
     1922                   | ((src_pixel >> 8) & 0x0000ff00);
     1923        } else {
     1924            return src_pixel;
     1925        }
     1926    } else {  // GL_RGBA
     1927        if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
     1928            return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
     1929        } else {
     1930            return ((src_pixel << 16) & 0xff0000)
     1931                   | ((src_pixel >> 16) & 0xff)
     1932                   | (src_pixel & 0xff00ff00);
     1933        }
     1934    }
     1935}
     1936
     1937QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format)
     1938{
     1939    return qt_gl_convertToGLFormatHelper(src_pixel, texture_format);
    16751940}
    16761941
    16771942static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
    16781943{
    1679     Q_ASSERT(dst.size() == img.size());
    16801944    Q_ASSERT(dst.depth() == 32);
    16811945    Q_ASSERT(img.depth() == 32);
    16821946
    1683     const int width = img.width();
    1684     const int height = img.height();
    1685     const uint *p = (const uint*) img.scanLine(img.height() - 1);
    1686     uint *q = (uint*) dst.scanLine(0);
    1687 
    1688     if (texture_format == GL_BGRA) {
    1689         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
    1690             // mirror + swizzle
    1691             for (int i=0; i < height; ++i) {
    1692                 const uint *end = p + width;
    1693                 while (p < end) {
    1694                     *q = ((*p << 24) & 0xff000000)
    1695                          | ((*p >> 24) & 0x000000ff)
    1696                          | ((*p << 8) & 0x00ff0000)
    1697                          | ((*p >> 8) & 0x0000ff00);
    1698                     p++;
    1699                     q++;
     1947    if (dst.size() != img.size()) {
     1948        int target_width = dst.width();
     1949        int target_height = dst.height();
     1950        qreal sx = target_width / qreal(img.width());
     1951        qreal sy = target_height / qreal(img.height());
     1952
     1953        quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
     1954        uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
     1955        int sbpl = img.bytesPerLine();
     1956        int dbpl = dst.bytesPerLine();
     1957
     1958        int ix = int(0x00010000 / sx);
     1959        int iy = int(0x00010000 / sy);
     1960
     1961        quint32 basex = int(0.5 * ix);
     1962        quint32 srcy = int(0.5 * iy);
     1963
     1964        // scale, swizzle and mirror in one loop
     1965        while (target_height--) {
     1966            const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
     1967            int srcx = basex;
     1968            for (int x=0; x<target_width; ++x) {
     1969                dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
     1970                srcx += ix;
     1971            }
     1972            dest = (quint32 *)(((uchar *) dest) + dbpl);
     1973            srcy += iy;
     1974        }
     1975    } else {
     1976        const int width = img.width();
     1977        const int height = img.height();
     1978        const uint *p = (const uint*) img.scanLine(img.height() - 1);
     1979        uint *q = (uint*) dst.scanLine(0);
     1980
     1981        if (texture_format == GL_BGRA) {
     1982            if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
     1983                // mirror + swizzle
     1984                for (int i=0; i < height; ++i) {
     1985                    const uint *end = p + width;
     1986                    while (p < end) {
     1987                        *q = ((*p << 24) & 0xff000000)
     1988                             | ((*p >> 24) & 0x000000ff)
     1989                             | ((*p << 8) & 0x00ff0000)
     1990                             | ((*p >> 8) & 0x0000ff00);
     1991                        p++;
     1992                        q++;
     1993                    }
     1994                    p -= 2 * width;
    17001995                }
    1701                 p -= 2 * width;
     1996            } else {
     1997                const uint bytesPerLine = img.bytesPerLine();
     1998                for (int i=0; i < height; ++i) {
     1999                    memcpy(q, p, bytesPerLine);
     2000                    q += width;
     2001                    p -= width;
     2002                }
    17022003            }
    17032004        } else {
    1704             const uint bytesPerLine = img.bytesPerLine();
    1705             for (int i=0; i < height; ++i) {
    1706                 memcpy(q, p, bytesPerLine);
    1707                 q += width;
    1708                 p -= width;
    1709             }
    1710         }
    1711     } else {
    1712         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
    1713             for (int i=0; i < height; ++i) {
    1714                 const uint *end = p + width;
    1715                 while (p < end) {
    1716                     *q = (*p << 8) | ((*p >> 24) & 0xFF);
    1717                     p++;
    1718                     q++;
     2005            if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
     2006                for (int i=0; i < height; ++i) {
     2007                    const uint *end = p + width;
     2008                    while (p < end) {
     2009                        *q = (*p << 8) | ((*p >> 24) & 0xff);
     2010                        p++;
     2011                        q++;
     2012                    }
     2013                    p -= 2 * width;
    17192014                }
    1720                 p -= 2 * width;
    1721             }
    1722         } else {
    1723             for (int i=0; i < height; ++i) {
    1724                 const uint *end = p + width;
    1725                 while (p < end) {
    1726                     *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
    1727                     p++;
    1728                     q++;
     2015            } else {
     2016                for (int i=0; i < height; ++i) {
     2017                    const uint *end = p + width;
     2018                    while (p < end) {
     2019                        *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
     2020                        p++;
     2021                        q++;
     2022                    }
     2023                    p -= 2 * width;
    17292024                }
    1730                 p -= 2 * width;
    17312025            }
    17322026        }
     
    17462040}
    17472041
    1748 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
    1749                                       const qint64 key, bool clean)
     2042/*! \internal */
     2043QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
     2044                                           QGLContext::BindOptions options)
     2045{
     2046    const qint64 key = image.cacheKey();
     2047    QGLTexture *texture = textureCacheLookup(key, target);
     2048    if (texture) {
     2049        glBindTexture(target, texture->id);
     2050        return texture;
     2051    }
     2052
     2053    if (!texture)
     2054        texture = bindTexture(image, target, format, key, options);
     2055    // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
     2056    Q_ASSERT(texture);
     2057
     2058    if (texture->id > 0)
     2059        QImagePixmapCleanupHooks::enableCleanupHooks(image);
     2060
     2061    return texture;
     2062}
     2063
     2064// #define QGL_BIND_TEXTURE_DEBUG
     2065
     2066// map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
     2067static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
     2068{
     2069    const int width = img.width();
     2070    const int height = img.height();
     2071
     2072    if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
     2073        || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
     2074    {
     2075        for (int i = 0; i < height; ++i) {
     2076            uint *p = (uint *) img.scanLine(i);
     2077            for (int x = 0; x < width; ++x)
     2078                p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
     2079        }
     2080    } else {
     2081        for (int i = 0; i < height; ++i) {
     2082            uint *p = (uint *) img.scanLine(i);
     2083            for (int x = 0; x < width; ++x)
     2084                p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
     2085        }
     2086    }
     2087}
     2088
     2089QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
     2090                                           const qint64 key, QGLContext::BindOptions options)
    17502091{
    17512092    Q_Q(QGLContext);
    17522093
    1753     QGLContext *ctx = q;
    1754 
    1755     bool use_pbo = false;
    1756     if (QGLExtensions::glExtensions & QGLExtensions::PixelBufferObject) {
    1757 
    1758         use_pbo = qt_resolve_buffer_extensions(ctx);
    1759         if (use_pbo && pbo == 0)
    1760             glGenBuffersARB(1, &pbo);
    1761     }
    1762 
    1763     // the GL_BGRA format is only present in GL version >= 1.2
    1764     GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
    1765                             ? GL_BGRA : GL_RGBA;
    1766     if (!qt_tex_cache) {
    1767         qt_tex_cache = new QGLTextureCache(qt_tex_cache_limit);
    1768         qt_pixmap_cleanup_hook_64 = qt_gl_clean_cache;
    1769         qt_image_cleanup_hook_64 = qt_gl_clean_cache;
    1770     }
     2094#ifdef QGL_BIND_TEXTURE_DEBUG
     2095    printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x\n",
     2096           image.width(), image.height(), internalFormat, int(options));
     2097    QTime time;
     2098    time.start();
     2099#endif
     2100
     2101#ifndef QT_NO_DEBUG
     2102    // Reset the gl error stack...git
     2103    while (glGetError() != GL_NO_ERROR) ;
     2104#endif
    17712105
    17722106    // Scale the pixmap if needed. GL textures needs to have the
    1773     // dimensions 2^n+2(border) x 2^m+2(border).
     2107    // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
     2108    // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
    17742109    int tx_w = qt_next_power_of_two(image.width());
    17752110    int tx_h = qt_next_power_of_two(image.height());
    17762111
    1777     // Note: the clean param is only true when a texture is bound
    1778     // from the QOpenGLPaintEngine - in that case we have to force
    1779     // a premultiplied texture format
    17802112    QImage img = image;
    1781     if (( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&
    1782           !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) )
     2113    if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
     2114        && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
    17832115        && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
    17842116    {
    1785         img = image.scaled(tx_w, tx_h);
    1786     }
     2117        img = img.scaled(tx_w, tx_h);
     2118#ifdef QGL_BIND_TEXTURE_DEBUG
     2119        printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
     2120
     2121#endif
     2122    }
     2123
     2124    GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
    17872125
    17882126    GLuint tx_id;
    17892127    glGenTextures(1, &tx_id);
    17902128    glBindTexture(target, tx_id);
    1791     glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     2129    glTexParameterf(target, GL_TEXTURE_MAG_FILTER, filtering);
     2130
     2131#if defined(QT_OPENGL_ES_2)
     2132    bool genMipmap = false;
     2133#endif
    17922134    if (glFormat.directRendering()
    1793         && QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap
    1794         && target == GL_TEXTURE_2D && !clean)
     2135        && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
     2136        && target == GL_TEXTURE_2D
     2137        && (options & QGLContext::MipmapBindOption))
    17952138    {
     2139#ifdef QGL_BIND_TEXTURE_DEBUG
     2140        printf(" - generating mipmaps (%d ms)\n", time.elapsed());
     2141#endif
     2142#if !defined(QT_OPENGL_ES_2)
    17962143        glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
    17972144#ifndef QT_OPENGL_ES
     
    18002147        glTexParameterf(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
    18012148#endif
    1802         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    1803 
    1804         // Mipmap generation causes huge slowdown with PBO's for some reason
    1805         use_pbo = false;
     2149#else
     2150        glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
     2151        genMipmap = true;
     2152#endif
     2153        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
     2154                        ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
    18062155    } else {
    1807         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    1808     }
    1809 
    1810     uchar *ptr = 0;
    1811     if (use_pbo) {
    1812         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
    1813         glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB);
    1814         ptr = reinterpret_cast<uchar *>(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB));
    1815     }
    1816 
    1817     if (ptr) {
    1818         QImage::Format target_format = img.format();
    1819         if (clean || img.format() != QImage::Format_ARGB32)
    1820             target_format = QImage::Format_ARGB32_Premultiplied;
    1821 
    1822         QImage buffer(ptr, img.width(), img.height(), target_format);
    1823         convertToGLFormatHelper(buffer, img.convertToFormat(target_format), texture_format);
    1824         glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
    1825         glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format, GL_UNSIGNED_BYTE, 0);
     2156        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
     2157    }
     2158
     2159    QImage::Format target_format = img.format();
     2160    bool premul = options & QGLContext::PremultipliedAlphaBindOption;
     2161    GLenum externalFormat;
     2162    GLuint pixel_type;
     2163    if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
     2164        externalFormat = GL_BGRA;
     2165        pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
    18262166    } else {
    1827         QImage tx = convertToGLFormat(img, clean, texture_format);
    1828         glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format,
    1829                      GL_UNSIGNED_BYTE, tx.bits());
    1830     }
    1831 
    1832     if (use_pbo)
    1833         glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
     2167        externalFormat = GL_RGBA;
     2168        pixel_type = GL_UNSIGNED_BYTE;
     2169    }
     2170
     2171    switch (target_format) {
     2172    case QImage::Format_ARGB32:
     2173        if (premul) {
     2174            img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
     2175#ifdef QGL_BIND_TEXTURE_DEBUG
     2176            printf(" - converting ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
     2177#endif
     2178        }
     2179        break;
     2180    case QImage::Format_ARGB32_Premultiplied:
     2181        if (!premul) {
     2182            img = img.convertToFormat(target_format = QImage::Format_ARGB32);
     2183#ifdef QGL_BIND_TEXTURE_DEBUG
     2184            printf(" - converting ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
     2185#endif
     2186        }
     2187        break;
     2188    case QImage::Format_RGB16:
     2189        pixel_type = GL_UNSIGNED_SHORT_5_6_5;
     2190        externalFormat = GL_RGB;
     2191        internalFormat = GL_RGB;
     2192        break;
     2193    case QImage::Format_RGB32:
     2194        break;
     2195    default:
     2196        if (img.hasAlphaChannel()) {
     2197            img = img.convertToFormat(premul
     2198                                      ? QImage::Format_ARGB32_Premultiplied
     2199                                      : QImage::Format_ARGB32);
     2200#ifdef QGL_BIND_TEXTURE_DEBUG
     2201            printf(" - converting to 32-bit alpha format (%d ms)\n", time.elapsed());
     2202#endif
     2203        } else {
     2204            img = img.convertToFormat(QImage::Format_RGB32);
     2205#ifdef QGL_BIND_TEXTURE_DEBUG
     2206            printf(" - converting to 32-bit (%d ms)\n", time.elapsed());
     2207#endif
     2208        }
     2209    }
     2210
     2211    if (options & QGLContext::InvertedYBindOption) {
     2212#ifdef QGL_BIND_TEXTURE_DEBUG
     2213            printf(" - flipping bits over y (%d ms)\n", time.elapsed());
     2214#endif
     2215        if (img.isDetached()) {
     2216            int ipl = img.bytesPerLine() / 4;
     2217            int h = img.height();
     2218            for (int y=0; y<h/2; ++y) {
     2219                int *a = (int *) img.scanLine(y);
     2220                int *b = (int *) img.scanLine(h - y - 1);
     2221                for (int x=0; x<ipl; ++x)
     2222                    qSwap(a[x], b[x]);
     2223            }
     2224        } else {
     2225            // Create a new image and copy across.  If we use the
     2226            // above in-place code then a full copy of the image is
     2227            // made before the lines are swapped, which processes the
     2228            // data twice.  This version should only do it once.
     2229            img = img.mirrored();
     2230        }
     2231    }
     2232
     2233    if (externalFormat == GL_RGBA) {
     2234#ifdef QGL_BIND_TEXTURE_DEBUG
     2235            printf(" - doing byte swapping (%d ms)\n", time.elapsed());
     2236#endif
     2237        // The only case where we end up with a depth different from
     2238        // 32 in the switch above is for the RGB16 case, where we set
     2239        // the format to GL_RGB
     2240        Q_ASSERT(img.depth() == 32);
     2241        qgl_byteSwapImage(img, pixel_type);
     2242    }
     2243#ifdef QT_OPENGL_ES
     2244    // OpenGL/ES requires that the internal and external formats be identical.
     2245    // This is typically used to convert GL_RGBA into GL_BGRA.
     2246    // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
     2247    internalFormat = externalFormat;
     2248    if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
     2249        pixel_type = GL_UNSIGNED_BYTE;
     2250#endif
     2251#ifdef QGL_BIND_TEXTURE_DEBUG
     2252    printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
     2253           img.format(), externalFormat, internalFormat, pixel_type);
     2254#endif
     2255
     2256    const QImage &constRef = img; // to avoid detach in bits()...
     2257    glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
     2258                 pixel_type, constRef.bits());
     2259#if defined(QT_OPENGL_ES_2)
     2260    if (genMipmap)
     2261        glGenerateMipmap(target);
     2262#endif
     2263#ifndef QT_NO_DEBUG
     2264    GLenum error = glGetError();
     2265    if (error != GL_NO_ERROR) {
     2266        qWarning(" - texture upload failed, error code 0x%x\n", error);
     2267    }
     2268#endif
     2269
     2270#ifdef QGL_BIND_TEXTURE_DEBUG
     2271    static int totalUploadTime = 0;
     2272    totalUploadTime += time.elapsed();
     2273    printf(" - upload done in (%d ms) time=%d\n", time.elapsed(), totalUploadTime);
     2274#endif
     2275
    18342276
    18352277    // this assumes the size of a texture is always smaller than the max cache size
    18362278    int cost = img.width()*img.height()*4/1024;
    1837     if (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost()) {
    1838         // the cache is full - make an attempt to remove something
    1839         const QList<qint64> keys = qt_tex_cache->keys();
    1840         int i = 0;
    1841         while (i < qt_tex_cache->count()
    1842                && (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost())) {
    1843             QGLTexture *tex = qt_tex_cache->object(keys.at(i));
    1844             if (tex->context == q)
    1845                 qt_tex_cache->remove(keys.at(i));
    1846             ++i;
     2279    QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
     2280    QGLTextureCache::instance()->insert(q, key, texture, cost);
     2281    return texture;
     2282}
     2283
     2284QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
     2285{
     2286    Q_Q(QGLContext);
     2287    QGLTexture *texture = QGLTextureCache::instance()->getTexture(key);
     2288    if (texture && texture->target == target
     2289        && (texture->context == q || QGLContext::areSharing(q, texture->context)))
     2290    {
     2291        return texture;
     2292    }
     2293    return 0;
     2294}
     2295
     2296
     2297/*! \internal */
     2298QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
     2299{
     2300    Q_Q(QGLContext);
     2301    QPixmapData *pd = pixmap.pixmapData();
     2302#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     2303    if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
     2304        const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
     2305
     2306        if (data->isValidContext(q)) {
     2307            data->bind();
     2308            return data->texture();
    18472309        }
    18482310    }
    1849     qt_tex_cache->insert(key, new QGLTexture(q, tx_id, target, clean), cost);
    1850     return tx_id;
    1851 }
    1852 
    1853 bool QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target, GLuint *id)
    1854 {
    1855     Q_Q(QGLContext);
    1856     if (qt_tex_cache) {
    1857         QGLTexture *texture = qt_tex_cache->object(key);
    1858         if (texture && texture->target == target
    1859             && (texture->context == q || qgl_share_reg()->checkSharing(q, texture->context)))
    1860         {
    1861             *id = texture->id;
    1862             return true;
     2311#else
     2312    Q_UNUSED(pd);
     2313    Q_UNUSED(q);
     2314#endif
     2315
     2316    const qint64 key = pixmap.cacheKey();
     2317    QGLTexture *texture = textureCacheLookup(key, target);
     2318    if (texture) {
     2319        glBindTexture(target, texture->id);
     2320        return texture;
     2321    }
     2322
     2323#if defined(Q_WS_X11)
     2324    // Try to use texture_from_pixmap
     2325    if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) {
     2326        texture = bindTextureFromNativePixmap(pd, key, options);
     2327        if (texture) {
     2328            texture->options |= QGLContext::MemoryManagedBindOption;
     2329            texture->boundPixmap = pd;
     2330            boundPixmaps.insert(pd, QPixmap(pixmap));
    18632331        }
    18642332    }
    1865     return false;
    1866 }
    1867 
    1868 /*! \internal */
    1869 GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean)
    1870 {
    1871     const qint64 key = image.cacheKey();
    1872     GLuint id;
    1873     if (textureCacheLookup(key, target, &id)) {
    1874         glBindTexture(target, id);
    1875         return id;
    1876     }
    1877     GLuint cached = bindTexture(image, target, format, key, clean);
    1878     const_cast<QImage &>(image).data_ptr()->is_cached = (cached > 0);
    1879     return cached;
    1880 }
    1881 
    1882 /*! \internal */
    1883 GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean)
    1884 {
    1885 #if !defined(QT_OPENGL_ES_2)
    1886     if (target == qt_gl_preferredTextureTarget() && pixmap.pixmapData()->classId() == QPixmapData::OpenGLClass) {
    1887         const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pixmap.pixmapData());
    1888 
    1889         if (data->isValidContext(QGLContext::currentContext()))
    1890             return data->bind();
    1891     }
    1892 #endif
    1893 
    1894     const qint64 key = pixmap.cacheKey();
    1895     GLuint id;
    1896     if (textureCacheLookup(key, target, &id)) {
    1897         glBindTexture(target, id);
    1898         return id;
    1899     }
    1900     GLuint cached = bindTexture(pixmap.toImage(), target, format, key, clean);
    1901     const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = (cached > 0);
    1902     return cached;
     2333#endif
     2334
     2335    if (!texture)
     2336        texture = bindTexture(pixmap.toImage(), target, format, key, options);
     2337    // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
     2338    Q_ASSERT(texture);
     2339
     2340    if (texture->id > 0)
     2341        QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
     2342
     2343    return texture;
    19032344}
    19042345
     
    19392380
    19402381/*!
     2382  Generates and binds a 2D GL texture to the current context, based
     2383  on \a image. The generated texture id is returned and can be used in
     2384  later \c glBindTexture() calls.
     2385
     2386  \overload
     2387*/
     2388GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
     2389{
     2390    if (image.isNull())
     2391        return 0;
     2392
     2393    Q_D(QGLContext);
     2394    QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
     2395    return texture->id;
     2396}
     2397
     2398/*!
     2399    \since 4.6
     2400
    19412401    Generates and binds a 2D GL texture to the current context, based
    19422402    on \a image. The generated texture id is returned and can be used
     
    19472407
    19482408    The \a format parameter sets the internal format for the
    1949     texture. The default format is \c GL_RGBA8.
    1950 
    1951     If the GL implementation supports the \c GL_SGIS_generate_mipmap
    1952     extension, mipmaps will be automatically generated for the
    1953     texture. Mipmap generation is only supported for the \c
    1954     GL_TEXTURE_2D target.
     2409    texture. The default format is \c GL_RGBA.
     2410
     2411    The binding \a options are a set of options used to decide how to
     2412    bind the texture to the context.
    19552413
    19562414    The texture that is generated is cached, so multiple calls to
     
    19632421    \sa deleteTexture()
    19642422*/
    1965 GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
    1966 {
     2423GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
     2424{
     2425    if (image.isNull())
     2426        return 0;
     2427
    19672428    Q_D(QGLContext);
    1968     return d->bindTexture(image, target, format, false);
     2429    QGLTexture *texture = d->bindTexture(image, target, format, false, options);
     2430    return texture->id;
    19692431}
    19702432
     
    19732435GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
    19742436{
     2437    if (image.isNull())
     2438        return 0;
     2439
    19752440    Q_D(QGLContext);
    1976     return d->bindTexture(image, GLenum(target), GLint(format), false);
     2441    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, DefaultBindOption);
     2442    return texture->id;
     2443}
     2444
     2445/*! \internal */
     2446GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
     2447                               BindOptions options)
     2448{
     2449    if (image.isNull())
     2450        return 0;
     2451
     2452    Q_D(QGLContext);
     2453    QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false, options);
     2454    return texture->id;
    19772455}
    19782456#endif
     
    19842462GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
    19852463{
     2464    if (pixmap.isNull())
     2465        return 0;
     2466
    19862467    Q_D(QGLContext);
    1987     return d->bindTexture(pixmap, target, format, false);
     2468    QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
     2469    return texture->id;
     2470}
     2471
     2472/*!
     2473  \overload
     2474  \since 4.6
     2475
     2476  Generates and binds a 2D GL texture to the current context, based
     2477  on \a pixmap.
     2478*/
     2479GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
     2480{
     2481    if (pixmap.isNull())
     2482        return 0;
     2483
     2484    Q_D(QGLContext);
     2485    QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
     2486    return texture->id;
    19882487}
    19892488
     
    19922491GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format)
    19932492{
     2493    if (pixmap.isNull())
     2494        return 0;
     2495
    19942496    Q_D(QGLContext);
    1995     return d->bindTexture(pixmap, GLenum(target), GLint(format), false);
     2497    QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), DefaultBindOption);
     2498    return texture->id;
     2499}
     2500/*! \internal */
     2501GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
     2502                               BindOptions options)
     2503{
     2504    if (pixmap.isNull())
     2505        return 0;
     2506
     2507    Q_D(QGLContext);
     2508    QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), options);
     2509    return texture->id;
    19962510}
    19972511#endif
     
    20062520void QGLContext::deleteTexture(GLuint id)
    20072521{
    2008     if (qt_tex_cache) {
    2009         QList<qint64> keys = qt_tex_cache->keys();
    2010         for (int i = 0; i < keys.size(); ++i) {
    2011             QGLTexture *tex = qt_tex_cache->object(keys.at(i));
    2012             if (tex->id == id && tex->context == this) {
    2013                 tex->clean = true; // forces a glDeleteTextures() call
    2014                 qt_tex_cache->remove(keys.at(i));
    2015                 return;
    2016             }
    2017         }
    2018     }
     2522    Q_D(QGLContext);
     2523
     2524    if (QGLTextureCache::instance()->remove(this, id))
     2525        return;
    20192526
    20202527    // check the DDS cache if the texture wasn't found in the pixmap/image
    20212528    // cache
    2022     QList<QString> ddsKeys = qgl_dds_cache()->keys();
     2529    QGLDDSCache *dds_cache = &(d->group->m_dds_cache);
     2530    QList<QString> ddsKeys = dds_cache->keys();
    20232531    for (int i = 0; i < ddsKeys.size(); ++i) {
    2024         GLuint texture = qgl_dds_cache()->value(ddsKeys.at(i));
     2532        GLuint texture = dds_cache->value(ddsKeys.at(i));
    20252533        if (id == texture) {
    20262534            glDeleteTextures(1, &texture);
    2027             qgl_dds_cache()->remove(ddsKeys.at(i));
     2535            dds_cache->remove(ddsKeys.at(i));
    20282536            return;
    20292537        }
     
    20392547#endif
    20402548
    2041 // qpaintengine_opengl.cpp
     2549void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
     2550{
     2551    qreal left = r.left();
     2552    qreal right = r.right();
     2553    qreal top = r.top();
     2554    qreal bottom = r.bottom();
     2555
     2556    array[0] = f2vt(left);
     2557    array[1] = f2vt(top);
     2558    array[2] = f2vt(right);
     2559    array[3] = f2vt(top);
     2560    array[4] = f2vt(right);
     2561    array[5] = f2vt(bottom);
     2562    array[6] = f2vt(left);
     2563    array[7] = f2vt(bottom);
     2564}
     2565
     2566void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
     2567{
     2568    array[0] = f2vt(x1);
     2569    array[1] = f2vt(y1);
     2570    array[2] = f2vt(x2);
     2571    array[3] = f2vt(y1);
     2572    array[4] = f2vt(x2);
     2573    array[5] = f2vt(y2);
     2574    array[6] = f2vt(x1);
     2575    array[7] = f2vt(y2);
     2576}
     2577
    20422578#if !defined(QT_OPENGL_ES_2)
    2043 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
    2044 #else
    2045 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array) {};
    2046 #endif
    20472579
    20482580static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
     
    20742606    qt_add_rect_to_array(target, vertexArray);
    20752607
    2076 #if !defined(QT_OPENGL_ES_2)
    20772608    glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    20782609    glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     
    20842615    glDisableClientState(GL_VERTEX_ARRAY);
    20852616    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    2086 #endif
    2087 }
     2617}
     2618
     2619#endif // !QT_OPENGL_ES_2
    20882620
    20892621/*!
     
    20942626    texture target.
    20952627
    2096     Equivalent to the corresponding QGLContext::drawTexture().
     2628    \note This function is not supported under OpenGL/ES 2.0.
    20972629*/
    20982630void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
    20992631{
     2632#ifndef QT_OPENGL_ES_2
    21002633#ifdef QT_OPENGL_ES
    21012634    if (textureTarget != GL_TEXTURE_2D) {
     
    21212654    glBindTexture(textureTarget, oldTexture);
    21222655#endif
     2656#else
     2657    Q_UNUSED(target);
     2658    Q_UNUSED(textureId);
     2659    Q_UNUSED(textureTarget);
     2660    qWarning("drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES/2.0");
     2661#endif
    21232662}
    21242663
     
    21372676    space. The \a textureTarget should be a 2D texture target.
    21382677
    2139     Equivalent to the corresponding QGLContext::drawTexture().
     2678    \note This function is not supported under OpenGL/ES.
    21402679*/
    21412680void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
     
    21882727void QGLContext::setTextureCacheLimit(int size)
    21892728{
    2190     qt_tex_cache_limit = size;
    2191     if (qt_tex_cache)
    2192         qt_tex_cache->setMaxCost(qt_tex_cache_limit);
     2729    QGLTextureCache::instance()->setMaxCost(size);
    21932730}
    21942731
     
    22002737int QGLContext::textureCacheLimit()
    22012738{
    2202     return qt_tex_cache_limit;
     2739    return QGLTextureCache::instance()->maxCost();
    22032740}
    22042741
     
    22792816    formats.
    22802817*/
     2818
     2819/*!
     2820    Returns true if \a context1 and \a context2 are sharing their
     2821    GL resources such as textures, shader programs, etc;
     2822    otherwise returns false.
     2823
     2824    \since 4.6
     2825*/
     2826bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *context2)
     2827{
     2828    if (!context1 || !context2)
     2829        return false;
     2830    return context1->d_ptr->group == context2->d_ptr->group;
     2831}
    22812832
    22822833/*!
     
    23992950    reset();
    24002951    d->valid = chooseContext(shareContext);
     2952    if (d->valid && d->paintDevice->devType() == QInternal::Widget) {
     2953        QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
     2954        wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
     2955    }
    24012956    if (d->sharing)  // ok, we managed to share
    24022957        qgl_share_reg()->addShare(this, shareContext);
     
    24192974{
    24202975    Q_D(const QGLContext);
    2421     return d->sharing;
     2976    return d->group->isSharing();
    24222977}
    24232978
     
    24743029const QGLContext* QGLContext::currentContext()
    24753030{
    2476     if (qgl_context_storage.hasLocalData())
    2477         return qgl_context_storage.localData()->context;
     3031    QGLThreadContext *threadContext = qgl_context_storage.localData();
     3032    if (threadContext)
     3033        return threadContext->context;
    24783034    return 0;
     3035}
     3036
     3037void QGLContextPrivate::setCurrentContext(QGLContext *context)
     3038{
     3039    QGLThreadContext *threadContext = qgl_context_storage.localData();
     3040    if (!threadContext) {
     3041        if (!QThread::currentThread()) {
     3042            // We don't have a current QThread, so just set the static.
     3043            QGLContext::currentCtx = context;
     3044            return;
     3045        }
     3046        threadContext = new QGLThreadContext;
     3047        qgl_context_storage.setLocalData(threadContext);
     3048    }
     3049    threadContext->context = context;
     3050    QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe
    24793051}
    24803052
     
    24933065*/
    24943066
     3067/*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
     3068
     3069    \bold{Win32 only:} This virtual function chooses a pixel format
     3070    that matches the OpenGL \link setFormat() format\endlink.
     3071    Reimplement this function in a subclass if you need a custom
     3072    context.
     3073
     3074    \warning The \a dummyPfd pointer and \a pdc are used as a \c
     3075    PIXELFORMATDESCRIPTOR*. We use \c void to avoid using
     3076    Windows-specific types in our header files.
     3077
     3078    \sa chooseContext()
     3079*/
     3080
     3081/*! \fn void *QGLContext::chooseVisual()
     3082
     3083  \bold{X11 only:} This virtual function tries to find a visual that
     3084  matches the format, reducing the demands if the original request
     3085  cannot be met.
     3086
     3087  The algorithm for reducing the demands of the format is quite
     3088  simple-minded, so override this method in your subclass if your
     3089  application has spcific requirements on visual selection.
     3090
     3091  \sa chooseContext()
     3092*/
     3093
     3094/*! \fn void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
     3095  \internal
     3096
     3097  \bold{X11 only:} This virtual function chooses a visual that matches
     3098  the OpenGL \link format() format\endlink. Reimplement this function
     3099  in a subclass if you need a custom visual.
     3100
     3101  \sa chooseContext()
     3102*/
    24953103
    24963104/*!
     
    25613169    \brief The QGLWidget class is a widget for rendering OpenGL graphics.
    25623170
    2563     \ingroup multimedia
    2564     \mainclass
     3171    \ingroup painting-3D
     3172
    25653173
    25663174    QGLWidget provides functionality for displaying OpenGL graphics
     
    25773185    needs to be updated.
    25783186    \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
    2579     called whenever the the widget has been resized (and also when it
     3187    called whenever the widget has been resized (and also when it
    25803188    is shown for the first time because all newly created widgets get a
    25813189    resize event automatically).
     
    26033211    customized rendering \link QGLContext contexts\endlink.
    26043212
    2605     You can also share OpenGL display lists between QGLWidgets (see
     3213    You can also share OpenGL display lists between QGLWidget objects (see
    26063214    the documentation of the QGLWidget constructors for details).
    26073215
     
    28853493    Returns true if this widget's GL context is shared with another GL
    28863494    context, otherwise false is returned. Context sharing might not be
    2887     possible if the QGLWidgets use different formats.
     3495    possible if the widgets use different formats.
    28883496
    28893497    \sa format()
     
    29833591
    29843592  This method will try to keep display list and texture object sharing
    2985   in effect with other QGLWidgets, but changing the format might make
     3593  in effect with other QGLWidget objects, but changing the format might make
    29863594  sharing impossible. Use isSharing() to see if sharing is still in
    29873595  effect.
     
    30093617
    30103618/*
     3619  \fn void QGLWidget::setContext(QGLContext *context,
     3620                                 const QGLContext* shareContext,
     3621                                 bool deleteOldContext)
    30113622  \obsolete
    3012 
    3013   \fn void QGLWidget::setContext(QGLContext *context,
    3014                                   const QGLContext* shareContext,
    3015                                   bool deleteOldContext)
    30163623
    30173624  Sets a new context for this widget. The QGLContext \a context must
     
    31633770}
    31643771
    3165 
     3772/*! \fn bool QGLWidget::event(QEvent *e)
     3773  \reimp
     3774*/
    31663775#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
    3167 /*! \reimp */
    31683776bool QGLWidget::event(QEvent *e)
    31693777{
     
    31913799        doneCurrent();
    31923800    } else if (e->type() == QEvent::ParentChange) {
    3193         if (d->glcx->d_func()->screen != d->xinfo.screen()) {
     3801        // if we've reparented a window that has the current context
     3802        // bound, we need to rebind that context to the new window id
     3803        if (d->glcx == QGLContext::currentContext())
     3804            makeCurrent();
     3805
     3806        if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) {
    31943807            setContext(new QGLContext(d->glcx->requestedFormat(), this));
    31953808            // ### recreating the overlay isn't supported atm
    31963809        }
     3810    }
     3811
    31973812#if defined(QT_OPENGL_ES)
    3198         // The window may have been re-created during re-parent - if so, the EGL
     3813    // A re-parent is likely to destroy the X11 window and re-create it. It is important
     3814    // that we free the EGL surface _before_ the winID changes - otherwise we can leak.
     3815    if (e->type() == QEvent::ParentAboutToChange)
     3816        d->glcx->d_func()->destroyEglSurfaceForDevice();
     3817
     3818    if ((e->type() == QEvent::ParentChange) || (e->type() == QEvent::WindowStateChange)) {
     3819        // The window may have been re-created during re-parent or state change - if so, the EGL
    31993820        // surface will need to be re-created.
    32003821        d->recreateEglSurface(false);
    3201 #endif
    3202     }
     3822    }
     3823#endif
    32033824#elif defined(Q_WS_WIN)
    32043825    if (e->type() == QEvent::ParentChange) {
    32053826        QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this);
    3206         qgl_share_reg()->replaceShare(d->glcx, newContext);
    3207         setContext(newContext);
     3827        setContext(newContext, d->glcx);
     3828
    32083829        // the overlay needs to be recreated as well
    32093830        delete d->olcx;
     
    32843905    Renders the current scene on a pixmap and returns the pixmap.
    32853906
    3286     You can use this method on both visible and invisible QGLWidgets.
     3907    You can use this method on both visible and invisible QGLWidget objects.
    32873908
    32883909    This method will create a pixmap and a temporary QGLContext to
     
    34064027        const QVector<QColor> pal = QColormap::instance().colormap();
    34074028        if (pal.size()) {
    3408             res.setNumColors(pal.size());
     4029            res.setColorCount(pal.size());
    34094030            for (int i = 0; i < pal.size(); i++)
    34104031                res.setColor(i, pal.at(i).rgb());
     
    34704091    with the color \a c. Applies to this widgets GL context.
    34714092
     4093    \note This function is not supported on OpenGL/ES 2.0 systems.
     4094
    34724095    \sa qglClearColor(), QGLContext::currentContext(), QColor
    34734096*/
     
    34774100#if !defined(QT_OPENGL_ES_2)
    34784101#ifdef QT_OPENGL_ES
    3479     glColor4f(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0);
     4102    glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
    34804103#else
    34814104    Q_D(const QGLWidget);
     
    34834106    if (ctx) {
    34844107        if (ctx->format().rgba())
    3485             glColor4ub(c.red(), c.green(), c.blue(), c.alpha());
     4108            glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
    34864109        else if (!d->cmap.isEmpty()) { // QGLColormap in use?
    34874110            int i = d->cmap.find(c.rgb());
     
    34934116    }
    34944117#endif //QT_OPENGL_ES
     4118#else
     4119    Q_UNUSED(c);
    34954120#endif //QT_OPENGL_ES_2
    34964121}
     
    35074132{
    35084133#ifdef QT_OPENGL_ES
    3509     glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
    3510                  (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0);
     4134    glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
    35114135#else
    35124136    Q_D(const QGLWidget);
     
    35144138    if (ctx) {
    35154139        if (ctx->format().rgba())
    3516             glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
    3517                           (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0);
     4140            glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
    35184141        else if (!d->cmap.isEmpty()) { // QGLColormap in use?
    35194142            int i = d->cmap.find(c.rgb());
     
    35864209    will return the colormap for the child's top-level widget.
    35874210
    3588     If no colormap has been set for this widget, the QColormap
     4211    If no colormap has been set for this widget, the QGLColormap
    35894212    returned will be empty.
    35904213
    3591     \sa setColormap()
     4214    \sa setColormap(), QGLColormap::isEmpty()
    35924215*/
    35934216
     
    36094232    value used when generating the display lists for the font. The
    36104233    default value is 2000.
     4234
     4235    \note This function is not supported on OpenGL/ES systems.
    36114236*/
    36124237int QGLWidget::fontDisplayListBase(const QFont & font, int listBase)
    36134238{
     4239#ifndef QT_OPENGL_ES
    36144240    Q_D(QGLWidget);
    36154241    int base;
     
    36294255    if (font.styleStrategy() != QFont::NoAntialias) {
    36304256        GLfloat color[4];
    3631 #ifndef QT_OPENGL_ES
    36324257        glGetFloatv(GL_CURRENT_COLOR, color);
    3633 #endif
    36344258        color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
    36354259    }
     
    36544278    }
    36554279    return base;
    3656 }
     4280#else // QT_OPENGL_ES
     4281    Q_UNUSED(font);
     4282    Q_UNUSED(listBase);
     4283    return 0;
     4284#endif
     4285}
     4286
     4287#ifndef QT_OPENGL_ES
    36574288
    36584289static void qt_save_gl_state()
    36594290{
    3660 #ifndef QT_OPENGL_ES
    36614291    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
    36624292    glPushAttrib(GL_ALL_ATTRIB_BITS);
    3663 #endif
    3664 #if !defined(QT_OPENGL_ES_2)
    36654293    glMatrixMode(GL_TEXTURE);
    36664294    glPushMatrix();
     
    36754303    glDisable(GL_LIGHTING);
    36764304    glDisable(GL_STENCIL_TEST);
     4305    glDisable(GL_DEPTH_TEST);
    36774306    glEnable(GL_BLEND);
    36784307    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    3679 #endif // !defined(QT_OPENGL_ES_2)
    36804308}
    36814309
    36824310static void qt_restore_gl_state()
    36834311{
    3684 #if !defined(QT_OPENGL_ES_2)
    36854312    glMatrixMode(GL_TEXTURE);
    36864313    glPopMatrix();
     
    36894316    glMatrixMode(GL_MODELVIEW);
    36904317    glPopMatrix();
    3691 #endif // !defined(QT_OPENGL_ES_2)
    3692 #ifndef QT_OPENGL_ES
    36934318    glPopAttrib();
    36944319    glPopClientAttrib();
    3695 #endif
    36964320}
    36974321
     
    37004324{
    37014325    GLfloat color[4];
    3702 #ifndef QT_OPENGL_ES
    37034326    glGetFloatv(GL_CURRENT_COLOR, &color[0]);
    3704 #endif
    37054327
    37064328    QColor col;
     
    37164338    p->setFont(old_font);
    37174339}
     4340
     4341#endif // !QT_OPENGL_ES
    37184342
    37194343/*!
     
    37314355
    37324356   \note This function clears the stencil buffer.
     4357
     4358   \note This function is not supported on OpenGL/ES systems.
     4359
     4360   \note This function temporarily disables depth-testing when the
     4361   text is drawn.
     4362
     4363   \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
    37334364*/
    37344365
    37354366void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font, int)
    37364367{
     4368#ifndef QT_OPENGL_ES
    37374369    Q_D(QGLWidget);
    37384370    if (str.isEmpty() || !isValid())
     
    37404372
    37414373    GLint view[4];
    3742 #ifndef QT_OPENGL_ES
    37434374    bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
    37444375    if (!use_scissor_testing)
    37454376        glGetIntegerv(GL_VIEWPORT, &view[0]);
    3746 #else
    3747     bool use_scissor_testing = false;
    3748 #endif
    37494377    int width = d->glcx->device()->width();
    37504378    int height = d->glcx->device()->height();
    37514379    bool auto_swap = autoBufferSwap();
    37524380
     4381    QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
     4382    qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
    37534383    QPaintEngine *engine = paintEngine();
    37544384    QPainter *p;
     
    37594389        qt_save_gl_state();
    37604390
    3761 #if !defined(QT_OPENGL_ES_2)
    37624391        glDisable(GL_DEPTH_TEST);
    37634392        glViewport(0, 0, width, height);
    37644393        glMatrixMode(GL_PROJECTION);
    37654394        glLoadIdentity();
    3766 #ifndef QT_OPENGL_ES
    37674395        glOrtho(0, width, height, 0, 0, 1);
    3768 #else
    3769         glOrthof(0, width, height, 0, 0, 1);
    3770 #endif
    37714396        glMatrixMode(GL_MODELVIEW);
    37724397
    37734398        glLoadIdentity();
    3774 #endif // !defined(QT_OPENGL_ES_2)
    37754399    } else {
    37764400        setAutoBufferSwap(false);
    37774401        // disable glClear() as a result of QPainter::begin()
    3778         d->glcx->d_func()->clear_on_painter_begin = false;
     4402        d->disable_clear_on_painter_begin = true;
    37794403        p = new QPainter(this);
    37804404    }
     
    37994423        delete p;
    38004424        setAutoBufferSwap(auto_swap);
    3801         d->glcx->d_func()->clear_on_painter_begin = true;
    3802     }
     4425        d->disable_clear_on_painter_begin = false;
     4426    }
     4427    qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
     4428#else // QT_OPENGL_ES
     4429    Q_UNUSED(x);
     4430    Q_UNUSED(y);
     4431    Q_UNUSED(str);
     4432    Q_UNUSED(font);
     4433    qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
     4434#endif
    38034435}
    38044436
     
    38094441    can be useful if you want to annotate models with text labels and
    38104442    have the labels move with the model as it is rotated etc.
     4443
     4444    \note This function is not supported on OpenGL/ES systems.
     4445
     4446    \note If depth testing is enabled before this function is called,
     4447    then the drawn text will be depth-tested against the models that
     4448    have already been drawn in the scene.  Use \c{glDisable(GL_DEPTH_TEST)}
     4449    before calling this function to annotate the models without
     4450    depth-testing the text.
     4451
     4452    \l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
    38114453*/
    38124454void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font, int)
    38134455{
     4456#ifndef QT_OPENGL_ES
    38144457    Q_D(QGLWidget);
    38154458    if (str.isEmpty() || !isValid())
     
    38224465    GLdouble model[4][4], proj[4][4];
    38234466    GLint view[4];
    3824 #ifndef QT_OPENGL_ES
    38254467    glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]);
    38264468    glGetDoublev(GL_PROJECTION_MATRIX, &proj[0][0]);
    38274469    glGetIntegerv(GL_VIEWPORT, &view[0]);
    3828 #endif
    38294470    GLdouble win_x = 0, win_y = 0, win_z = 0;
    38304471    qgluProject(x, y, z, &model[0][0], &proj[0][0], &view[0],
     
    38324473    win_y = height - win_y; // y is inverted
    38334474
     4475    QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
     4476    qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
    38344477    QPaintEngine *engine = paintEngine();
    38354478    QPainter *p;
    38364479    bool reuse_painter = false;
    3837 #ifndef QT_OPENGL_ES
    38384480    bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
    38394481    bool use_scissor_testing = glIsEnabled(GL_SCISSOR_TEST);
    3840 #else
    3841     bool use_depth_testing = false;
    3842     bool use_scissor_testing = false;
    3843 #endif
    38444482
    38454483    if (engine->isActive()) {
     
    38504488        setAutoBufferSwap(false);
    38514489        // disable glClear() as a result of QPainter::begin()
    3852         d->glcx->d_func()->clear_on_painter_begin = false;
     4490        d->disable_clear_on_painter_begin = true;
    38534491        p = new QPainter(this);
    38544492    }
     
    38614499        glEnable(GL_SCISSOR_TEST);
    38624500    }
    3863 #if !defined(QT_OPENGL_ES_2)
    38644501    glMatrixMode(GL_PROJECTION);
    38654502    glLoadIdentity();
    38664503    glViewport(0, 0, width, height);
    3867 #ifndef QT_OPENGL_ES
    38684504    glOrtho(0, width, height, 0, 0, 1);
    3869 #else
    3870     glOrthof(0, width, height, 0, 0, 1);
    3871 #endif
    38724505    glMatrixMode(GL_MODELVIEW);
    38734506    glLoadIdentity();
     
    38764509    if (use_depth_testing)
    38774510        glEnable(GL_DEPTH_TEST);
    3878 #ifndef QT_OPENGL_ES
    38794511    glTranslated(0, 0, -win_z);
    3880 #else
    3881     glTranslatef(0, 0, -win_z);
    3882 #endif
    3883 #endif // !defined(QT_OPENGL_ES_2)
    38844512    qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font);
    38854513
     
    38904518        delete p;
    38914519        setAutoBufferSwap(auto_swap);
    3892         d->glcx->d_func()->clear_on_painter_begin = true;
    3893     }
     4520        d->disable_clear_on_painter_begin = false;
     4521    }
     4522    qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
     4523#else // QT_OPENGL_ES
     4524    Q_UNUSED(x);
     4525    Q_UNUSED(y);
     4526    Q_UNUSED(z);
     4527    Q_UNUSED(str);
     4528    Q_UNUSED(font);
     4529    qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
     4530#endif
    38944531}
    38954532
     
    39324569GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
    39334570{
     4571    if (image.isNull())
     4572        return 0;
     4573
    39344574    Q_D(QGLWidget);
    3935     return d->glcx->bindTexture(image, target, format);
    3936 }
     4575    return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
     4576}
     4577
     4578/*!
     4579  \overload
     4580  \since 4.6
     4581
     4582  The binding \a options are a set of options used to decide how to
     4583  bind the texture to the context.
     4584 */
     4585GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
     4586{
     4587    if (image.isNull())
     4588        return 0;
     4589
     4590    Q_D(QGLWidget);
     4591    return d->glcx->bindTexture(image, target, format, options);
     4592}
     4593
    39374594
    39384595#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
     
    39404597GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format)
    39414598{
     4599    if (image.isNull())
     4600        return 0;
     4601
    39424602   Q_D(QGLWidget);
    3943    return d->glcx->bindTexture(image, GLenum(target), GLint(format));
     4603   return d->glcx->bindTexture(image, GLenum(target), GLint(format), QGLContext::DefaultBindOption);
     4604}
     4605
     4606GLuint QGLWidget::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format,
     4607                              QGLContext::BindOptions options)
     4608{
     4609    if (image.isNull())
     4610        return 0;
     4611
     4612   Q_D(QGLWidget);
     4613   return d->glcx->bindTexture(image, GLenum(target), GLint(format), options);
    39444614}
    39454615#endif
     
    39534623GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
    39544624{
     4625    if (pixmap.isNull())
     4626        return 0;
     4627
    39554628    Q_D(QGLWidget);
    3956     return d->glcx->bindTexture(pixmap, target, format);
     4629    return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
     4630}
     4631
     4632/*!
     4633  \overload
     4634  \since 4.6
     4635
     4636  Generates and binds a 2D GL texture to the current context, based
     4637  on \a pixmap. The generated texture id is returned and can be used in
     4638
     4639  The binding \a options are a set of options used to decide how to
     4640  bind the texture to the context.
     4641 */
     4642GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
     4643                              QGLContext::BindOptions options)
     4644{
     4645    Q_D(QGLWidget);
     4646    return d->glcx->bindTexture(pixmap, target, format, options);
    39574647}
    39584648
     
    39624652{
    39634653    Q_D(QGLWidget);
    3964     return d->glcx->bindTexture(pixmap, target, format);
     4654    return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
     4655}
     4656
     4657GLuint QGLWidget::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format,
     4658                              QGLContext::BindOptions options)
     4659{
     4660    Q_D(QGLWidget);
     4661    return d->glcx->bindTexture(pixmap, target, format, options);
    39654662}
    39664663#endif
     
    40474744#endif
    40484745
    4049 #if defined(QT_OPENGL_ES_2)
    4050 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_engine)
     4746#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     4747Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
     4748#endif
     4749
     4750#ifndef QT_OPENGL_ES_2
     4751Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
     4752#endif
     4753
     4754Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
     4755{
     4756#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     4757    return qt_gl_engine();
     4758#elif defined(QT_OPENGL_ES_2)
     4759    return qt_gl_2_engine();
    40514760#else
    4052 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
    4053 #endif
    4054 
    4055 #ifdef Q_WS_QWS
    4056 Q_OPENGL_EXPORT QOpenGLPaintEngine* qt_qgl_paint_engine()
    4057 {
    4058 #if !defined(QT_OPENGL_ES_2)
    4059     return qt_gl_engine();
    4060 #else
    4061     return 0; // XXX
    4062 #endif
    4063 }
    4064 #endif
     4761    if (qt_gl_preferGL2Engine())
     4762        return qt_gl_2_engine();
     4763    else
     4764        return qt_gl_engine();
     4765#endif
     4766}
    40654767
    40664768/*!
     
    40724774QPaintEngine *QGLWidget::paintEngine() const
    40734775{
    4074     return qt_gl_engine();
     4776    return qt_qgl_paint_engine();
    40754777}
    40764778
     
    41324834void QGLExtensions::init_extensions()
    41334835{
    4134     QString extensions = QLatin1String(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
    4135     if (extensions.contains(QLatin1String("texture_rectangle")))
     4836    QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
     4837
     4838    if (extensions.match("GL_ARB_texture_rectangle"))
    41364839        glExtensions |= TextureRectangle;
    4137     if (extensions.contains(QLatin1String("multisample")))
     4840    if (extensions.match("GL_ARB_multisample"))
    41384841        glExtensions |= SampleBuffers;
    4139     if (extensions.contains(QLatin1String("generate_mipmap")))
     4842    if (extensions.match("GL_SGIS_generate_mipmap"))
    41404843        glExtensions |= GenerateMipmap;
    4141     if (extensions.contains(QLatin1String("texture_compression_s3tc")))
     4844    if (extensions.match("GL_ARB_texture_compression"))
    41424845        glExtensions |= TextureCompression;
    4143     if (extensions.contains(QLatin1String("ARB_fragment_program")))
     4846    if (extensions.match("GL_EXT_texture_compression_s3tc"))
     4847        glExtensions |= DDSTextureCompression;
     4848    if (extensions.match("GL_OES_compressed_ETC1_RGB8_texture"))
     4849        glExtensions |= ETC1TextureCompression;
     4850    if (extensions.match("GL_IMG_texture_compression_pvrtc"))
     4851        glExtensions |= PVRTCTextureCompression;
     4852    if (extensions.match("GL_ARB_fragment_program"))
    41444853        glExtensions |= FragmentProgram;
    4145     if (extensions.contains(QLatin1String("mirrored_repeat")))
     4854    if (extensions.match("GL_ARB_fragment_shader"))
     4855        glExtensions |= FragmentShader;
     4856    if (extensions.match("GL_ARB_texture_mirrored_repeat"))
    41464857        glExtensions |= MirroredRepeat;
    4147     if (extensions.contains(QLatin1String("EXT_framebuffer_object")))
     4858    if (extensions.match("GL_EXT_framebuffer_object"))
    41484859        glExtensions |= FramebufferObject;
    4149     if (extensions.contains(QLatin1String("EXT_stencil_two_side")))
     4860    if (extensions.match("GL_EXT_stencil_two_side"))
    41504861        glExtensions |= StencilTwoSide;
    4151     if (extensions.contains(QLatin1String("EXT_stencil_wrap")))
     4862    if (extensions.match("GL_EXT_stencil_wrap"))
    41524863        glExtensions |= StencilWrap;
    4153     if (extensions.contains(QLatin1String("EXT_packed_depth_stencil")))
     4864    if (extensions.match("GL_EXT_packed_depth_stencil"))
    41544865        glExtensions |= PackedDepthStencil;
    4155     if (extensions.contains(QLatin1String("GL_NV_float_buffer")))
     4866    if (extensions.match("GL_NV_float_buffer"))
    41564867        glExtensions |= NVFloatBuffer;
    4157     if (extensions.contains(QLatin1String("ARB_pixel_buffer_object")))
     4868    if (extensions.match("GL_ARB_pixel_buffer_object"))
    41584869        glExtensions |= PixelBufferObject;
    41594870#if defined(QT_OPENGL_ES_2)
    41604871    glExtensions |= FramebufferObject;
    41614872    glExtensions |= GenerateMipmap;
    4162 #endif
    4163 
    4164     QGLContext cx(QGLFormat::defaultFormat());
    4165     if (glExtensions & TextureCompression) {
    4166         qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
    4167     }
     4873    glExtensions |= FragmentShader;
     4874#endif
     4875#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     4876    if (extensions.match("GL_OES_framebuffer_object"))
     4877        glExtensions |= FramebufferObject;
     4878#endif
     4879#if defined(QT_OPENGL_ES)
     4880    if (extensions.match("GL_OES_packed_depth_stencil"))
     4881        glExtensions |= PackedDepthStencil;
     4882#endif
     4883    if (extensions.match("GL_ARB_framebuffer_object")) {
     4884        // ARB_framebuffer_object also includes EXT_framebuffer_blit.
     4885        glExtensions |= FramebufferObject;
     4886        glExtensions |= FramebufferBlit;
     4887    }
     4888
     4889    if (extensions.match("GL_EXT_framebuffer_blit"))
     4890        glExtensions |= FramebufferBlit;
     4891
     4892    if (extensions.match("GL_ARB_texture_non_power_of_two"))
     4893        glExtensions |= NPOTTextures;
     4894
     4895    if (extensions.match("GL_EXT_bgra"))
     4896        glExtensions |= BGRATextureFormat;
    41684897}
    41694898
     
    41744903{
    41754904    Q_Q(QGLWidget);
     4905
     4906    glDevice.setWidget(q);
    41764907
    41774908    QGLExtensions::init();
     
    41904921
    41914922#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
    4192 Q_GLOBAL_STATIC(QString, qt_gl_lib_name);
     4923Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
    41934924
    41944925Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name)
     
    42014932    if (qt_gl_lib_name()->isNull()) {
    42024933#if defined(Q_WS_X11) || defined(Q_WS_QWS)
    4203         return QString(QLatin1String("GL"));
     4934        return QLatin1String("GL");
    42044935#else // Q_WS_MAC
    42054936        return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
     
    42104941#endif
    42114942
     4943void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) {
     4944    Q_ASSERT(context && share);
     4945    if (context->d_ptr->group == share->d_ptr->group)
     4946        return;
     4947
     4948    // Make sure 'context' is not already shared with another group of contexts.
     4949    Q_ASSERT(context->d_ptr->group->m_refs == 1);
     4950
     4951    // Free 'context' group resources and make it use the same resources as 'share'.
     4952    QGLContextGroup *group = share->d_ptr->group;
     4953    delete context->d_ptr->group;
     4954    context->d_ptr->group = group;
     4955    group->m_refs.ref();
     4956
     4957    // Maintain a list of all the contexts in each group of sharing contexts.
     4958    // The list is empty if the "share" context wasn't sharing already.
     4959    if (group->m_shares.isEmpty())
     4960        group->m_shares.append(share);
     4961    group->m_shares.append(context);
     4962}
     4963
     4964QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) {
     4965    return context->d_ptr->group->m_shares;
     4966}
     4967
     4968void QGLShareRegister::removeShare(const QGLContext *context) {
     4969    // Remove the context from the group.
     4970    QGLContextGroup *group = context->d_ptr->group;
     4971    if (group->m_shares.isEmpty())
     4972        return;
     4973    group->m_shares.removeAll(context);
     4974
     4975    // Update context group representative.
     4976    Q_ASSERT(group->m_shares.size() != 0);
     4977    if (group->m_context == context)
     4978        group->m_context = group->m_shares[0];
     4979
     4980    // If there is only one context left, then make the list empty.
     4981    if (group->m_shares.size() == 1)
     4982        group->m_shares.clear();
     4983}
     4984
     4985QGLContextResource::QGLContextResource(FreeFunc f)
     4986    : free(f), active(0)
     4987{
     4988}
     4989
     4990QGLContextResource::~QGLContextResource()
     4991{
     4992#ifndef QT_NO_DEBUG
     4993    if (active != 0) {
     4994        qWarning("QtOpenGL: Resources are still available at program shutdown.\n"
     4995                 "          This is possibly caused by a leaked QGLWidget, \n"
     4996                 "          QGLFramebufferObject or QGLPixelBuffer.");
     4997    }
     4998#endif
     4999}
     5000
     5001void QGLContextResource::insert(const QGLContext *key, void *value)
     5002{
     5003    QGLContextGroup *group = QGLContextPrivate::contextGroup(key);
     5004    Q_ASSERT(!group->m_resources.contains(this));
     5005    group->m_resources.insert(this, value);
     5006    active.ref();
     5007}
     5008
     5009void *QGLContextResource::value(const QGLContext *key)
     5010{
     5011    QGLContextGroup *group = QGLContextPrivate::contextGroup(key);
     5012    return group->m_resources.value(this, 0);
     5013}
     5014
     5015void QGLContextResource::cleanup(const QGLContext *ctx, void *value)
     5016{
     5017    QGLShareContextScope scope(ctx);
     5018    free(value);
     5019    active.deref();
     5020}
     5021
     5022void QGLContextGroup::cleanupResources(const QGLContext *ctx)
     5023{
     5024    // If there are still shares, then no cleanup to be done yet.
     5025    if (m_shares.size() > 1)
     5026        return;
     5027
     5028    // Iterate over all resources and free each in turn.
     5029    QHash<QGLContextResource *, void *>::ConstIterator it;
     5030    for (it = m_resources.begin(); it != m_resources.end(); ++it)
     5031        it.key()->cleanup(ctx, it.value());
     5032}
     5033
     5034QGLSharedResourceGuard::~QGLSharedResourceGuard()
     5035{
     5036    if (m_group)
     5037        m_group->removeGuard(this);
     5038}
     5039
     5040void QGLSharedResourceGuard::setContext(const QGLContext *context)
     5041{
     5042    if (m_group)
     5043        m_group->removeGuard(this);
     5044    if (context) {
     5045        m_group = QGLContextPrivate::contextGroup(context);
     5046        m_group->addGuard(this);
     5047    } else {
     5048        m_group = 0;
     5049    }
     5050}
     5051
     5052QSize QGLTexture::bindCompressedTexture
     5053    (const QString& fileName, const char *format)
     5054{
     5055    QFile file(fileName);
     5056    if (!file.open(QIODevice::ReadOnly))
     5057        return QSize();
     5058    QByteArray contents = file.readAll();
     5059    file.close();
     5060    return bindCompressedTexture
     5061        (contents.constData(), contents.size(), format);
     5062}
     5063
     5064// PVR header format for container files that store textures compressed
     5065// with the ETC1, PVRTC2, and PVRTC4 encodings.  Format information from the
     5066// PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
     5067// "PVRTexTool Reference Manual, version 1.11f".
     5068struct PvrHeader
     5069{
     5070    quint32 headerSize;
     5071    quint32 height;
     5072    quint32 width;
     5073    quint32 mipMapCount;
     5074    quint32 flags;
     5075    quint32 dataSize;
     5076    quint32 bitsPerPixel;
     5077    quint32 redMask;
     5078    quint32 greenMask;
     5079    quint32 blueMask;
     5080    quint32 alphaMask;
     5081    quint32 magic;
     5082    quint32 surfaceCount;
     5083};
     5084
     5085#define PVR_MAGIC               0x21525650      // "PVR!" in little-endian
     5086
     5087#define PVR_FORMAT_MASK         0x000000FF
     5088#define PVR_FORMAT_PVRTC2       0x00000018
     5089#define PVR_FORMAT_PVRTC4       0x00000019
     5090#define PVR_FORMAT_ETC1         0x00000036
     5091
     5092#define PVR_HAS_MIPMAPS         0x00000100
     5093#define PVR_TWIDDLED            0x00000200
     5094#define PVR_NORMAL_MAP          0x00000400
     5095#define PVR_BORDER_ADDED        0x00000800
     5096#define PVR_CUBE_MAP            0x00001000
     5097#define PVR_FALSE_COLOR_MIPMAPS 0x00002000
     5098#define PVR_VOLUME_TEXTURE      0x00004000
     5099#define PVR_ALPHA_IN_TEXTURE    0x00008000
     5100#define PVR_VERTICAL_FLIP       0x00010000
     5101
     5102#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
     5103#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG      0x8C00
     5104#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG      0x8C01
     5105#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG     0x8C02
     5106#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG     0x8C03
     5107#endif
     5108
     5109#ifndef GL_ETC1_RGB8_OES
     5110#define GL_ETC1_RGB8_OES                        0x8D64
     5111#endif
     5112
     5113bool QGLTexture::canBindCompressedTexture
     5114    (const char *buf, int len, const char *format, bool *hasAlpha)
     5115{
     5116    if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
     5117        // Compressed texture loading only supported on little-endian
     5118        // systems such as x86 and ARM at the moment.
     5119        return false;
     5120    }
     5121    if (!format) {
     5122        // Auto-detect the format from the header.
     5123        if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
     5124            *hasAlpha = true;
     5125            return true;
     5126        } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
     5127            const PvrHeader *pvrHeader =
     5128                reinterpret_cast<const PvrHeader *>(buf);
     5129            *hasAlpha = (pvrHeader->alphaMask != 0);
     5130            return true;
     5131        }
     5132    } else {
     5133        // Validate the format against the header.
     5134        if (!qstricmp(format, "DDS")) {
     5135            if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
     5136                *hasAlpha = true;
     5137                return true;
     5138            }
     5139        } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
     5140            if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
     5141                const PvrHeader *pvrHeader =
     5142                    reinterpret_cast<const PvrHeader *>(buf);
     5143                *hasAlpha = (pvrHeader->alphaMask != 0);
     5144                return true;
     5145            }
     5146        }
     5147    }
     5148    return false;
     5149}
     5150
     5151#define ctx QGLContext::currentContext()
     5152
     5153QSize QGLTexture::bindCompressedTexture
     5154    (const char *buf, int len, const char *format)
     5155{
     5156    if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
     5157        // Compressed texture loading only supported on little-endian
     5158        // systems such as x86 and ARM at the moment.
     5159        return QSize();
     5160    }
     5161#if !defined(QT_OPENGL_ES)
     5162    if (!glCompressedTexImage2D) {
     5163        if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
     5164            qWarning("QGLContext::bindTexture(): The GL implementation does "
     5165                     "not support texture compression extensions.");
     5166            return QSize();
     5167        }
     5168        glCompressedTexImage2D = (_glCompressedTexImage2DARB) ctx->getProcAddress(QLatin1String("glCompressedTexImage2DARB"));
     5169        if (!glCompressedTexImage2D) {
     5170            qWarning("QGLContext::bindTexture(): could not resolve "
     5171                     "glCompressedTexImage2DARB.");
     5172            return QSize();
     5173        }
     5174    }
     5175#endif
     5176    if (!format) {
     5177        // Auto-detect the format from the header.
     5178        if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
     5179            return bindCompressedTextureDDS(buf, len);
     5180        else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
     5181            return bindCompressedTexturePVR(buf, len);
     5182    } else {
     5183        // Validate the format against the header.
     5184        if (!qstricmp(format, "DDS")) {
     5185            if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
     5186                return bindCompressedTextureDDS(buf, len);
     5187        } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
     5188            if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
     5189                return bindCompressedTexturePVR(buf, len);
     5190        }
     5191    }
     5192    return QSize();
     5193}
     5194
     5195QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
     5196{
     5197    // We only support 2D texture loading at present.
     5198    if (target != GL_TEXTURE_2D)
     5199        return QSize();
     5200
     5201    // Bail out if the necessary extension is not present.
     5202    if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
     5203        qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
     5204        return QSize();
     5205    }
     5206
     5207    const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
     5208    if (!ddsHeader->dwLinearSize) {
     5209        qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
     5210        return QSize();
     5211    }
     5212
     5213    int blockSize = 16;
     5214    GLenum format;
     5215
     5216    switch(ddsHeader->ddsPixelFormat.dwFourCC) {
     5217    case FOURCC_DXT1:
     5218        format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
     5219        blockSize = 8;
     5220        break;
     5221    case FOURCC_DXT3:
     5222        format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
     5223        break;
     5224    case FOURCC_DXT5:
     5225        format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
     5226        break;
     5227    default:
     5228        qWarning("QGLContext::bindTexture(): DDS image format not supported.");
     5229        return QSize();
     5230    }
     5231
     5232    const GLubyte *pixels =
     5233        reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
     5234
     5235    glGenTextures(1, &id);
     5236    glBindTexture(GL_TEXTURE_2D, id);
     5237    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     5238    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     5239
     5240    int size;
     5241    int offset = 0;
     5242    int available = len - int(ddsHeader->dwSize + 4);
     5243    int w = ddsHeader->dwWidth;
     5244    int h = ddsHeader->dwHeight;
     5245
     5246    // load mip-maps
     5247    for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
     5248        if (w == 0) w = 1;
     5249        if (h == 0) h = 1;
     5250
     5251        size = ((w+3)/4) * ((h+3)/4) * blockSize;
     5252        if (size > available)
     5253            break;
     5254        glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
     5255                               size, pixels + offset);
     5256        offset += size;
     5257        available -= size;
     5258
     5259        // half size for each mip-map level
     5260        w = w/2;
     5261        h = h/2;
     5262    }
     5263
     5264    // DDS images are not inverted.
     5265    options &= ~QGLContext::InvertedYBindOption;
     5266
     5267    return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
     5268}
     5269
     5270QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
     5271{
     5272    // We only support 2D texture loading at present.  Cube maps later.
     5273    if (target != GL_TEXTURE_2D)
     5274        return QSize();
     5275
     5276    // Determine which texture format we will be loading.
     5277    const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
     5278    GLenum textureFormat;
     5279    quint32 minWidth, minHeight;
     5280    switch (pvrHeader->flags & PVR_FORMAT_MASK) {
     5281    case PVR_FORMAT_PVRTC2:
     5282        if (pvrHeader->alphaMask)
     5283            textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
     5284        else
     5285            textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
     5286        minWidth = 16;
     5287        minHeight = 8;
     5288        break;
     5289
     5290    case PVR_FORMAT_PVRTC4:
     5291        if (pvrHeader->alphaMask)
     5292            textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
     5293        else
     5294            textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
     5295        minWidth = 8;
     5296        minHeight = 8;
     5297        break;
     5298
     5299    case PVR_FORMAT_ETC1:
     5300        textureFormat = GL_ETC1_RGB8_OES;
     5301        minWidth = 4;
     5302        minHeight = 4;
     5303        break;
     5304
     5305    default:
     5306        qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
     5307        return QSize();
     5308    }
     5309
     5310    // Bail out if the necessary extension is not present.
     5311    if (textureFormat == GL_ETC1_RGB8_OES) {
     5312        if (!(QGLExtensions::glExtensions &
     5313                    QGLExtensions::ETC1TextureCompression)) {
     5314            qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
     5315            return QSize();
     5316        }
     5317    } else {
     5318        if (!(QGLExtensions::glExtensions &
     5319                    QGLExtensions::PVRTCTextureCompression)) {
     5320            qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
     5321            return QSize();
     5322        }
     5323    }
     5324
     5325    // Boundary check on the buffer size.
     5326    quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
     5327    if (bufferSize > quint32(len)) {
     5328        qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
     5329        return QSize();
     5330    }
     5331
     5332    // Create the texture.
     5333    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     5334    glGenTextures(1, &id);
     5335    glBindTexture(GL_TEXTURE_2D, id);
     5336    if (pvrHeader->mipMapCount) {
     5337        if ((options & QGLContext::LinearFilteringBindOption) != 0) {
     5338            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     5339            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
     5340        } else {
     5341            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     5342            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
     5343        }
     5344    } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
     5345        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     5346        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     5347    } else {
     5348        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     5349        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     5350    }
     5351
     5352    // Load the compressed mipmap levels.
     5353    const GLubyte *buffer =
     5354        reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
     5355    bufferSize = pvrHeader->dataSize;
     5356    quint32 level = 0;
     5357    quint32 width = pvrHeader->width;
     5358    quint32 height = pvrHeader->height;
     5359    while (bufferSize > 0 && level < pvrHeader->mipMapCount) {
     5360        quint32 size =
     5361            (qMax(width, minWidth) * qMax(height, minHeight) *
     5362             pvrHeader->bitsPerPixel) / 8;
     5363        if (size > bufferSize)
     5364            break;
     5365        glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
     5366                               GLsizei(width), GLsizei(height), 0,
     5367                               GLsizei(size), buffer);
     5368        width /= 2;
     5369        height /= 2;
     5370        buffer += size;
     5371        ++level;
     5372    }
     5373
     5374    // Restore the default pixel alignment for later texture uploads.
     5375    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     5376
     5377    // Set the invert flag for the texture.  The "vertical flip"
     5378    // flag in PVR is the opposite sense to our sense of inversion.
     5379    if ((pvrHeader->flags & PVR_VERTICAL_FLIP) != 0)
     5380        options &= ~QGLContext::InvertedYBindOption;
     5381    else
     5382        options |= QGLContext::InvertedYBindOption;
     5383
     5384    return QSize(pvrHeader->width, pvrHeader->height);
     5385}
     5386
     5387#undef ctx
     5388
    42125389QT_END_NAMESPACE
  • trunk/src/opengl/qgl.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444
    4545#include <QtGui/qwidget.h>
     46#include <QtGui/qpaintengine.h>
    4647#include <QtOpenGL/qglcolormap.h>
    4748#include <QtCore/qmap.h>
     49#include <QtCore/qscopedpointer.h>
    4850
    4951QT_BEGIN_HEADER
     
    130132namespace QGL
    131133{
     134    Q_OPENGL_EXPORT void setPreferredPaintEngine(QPaintEngine::Type engineType);
     135
    132136    enum FormatOption {
    133137        DoubleBuffer            = 0x0001,
     
    255259    QGLFormatPrivate *d;
    256260
     261    void detach();
     262
    257263    friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
    258264    friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
     
    277283    void reset();
    278284
    279     // ### Qt 5: make format() return a const ref instead
     285    static bool areSharing(const QGLContext *context1, const QGLContext *context2);
     286
    280287    QGLFormat format() const;
    281288    QGLFormat requestedFormat() const;
     
    287294
    288295    virtual void swapBuffers() const;
     296
     297    enum BindOption {
     298        NoBindOption                            = 0x0000,
     299        InvertedYBindOption                     = 0x0001,
     300        MipmapBindOption                        = 0x0002,
     301        PremultipliedAlphaBindOption            = 0x0004,
     302        LinearFilteringBindOption               = 0x0008,
     303
     304        MemoryManagedBindOption                 = 0x0010, // internal flag
     305        CanFlipNativePixmapBindOption           = 0x0020, // internal flag
     306
     307        DefaultBindOption                       = LinearFilteringBindOption
     308                                                  | InvertedYBindOption
     309                                                  | MipmapBindOption,
     310        InternalBindOption                      = MemoryManagedBindOption
     311                                                  | PremultipliedAlphaBindOption
     312    };
     313    Q_DECLARE_FLAGS(BindOptions, BindOption)
     314
     315    GLuint bindTexture(const QImage &image, GLenum target, GLint format,
     316                       BindOptions options);
     317    GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
     318                       BindOptions options);
    289319
    290320    GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
     
    304334    GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D,
    305335                       QMacCompatGLint format = GL_RGBA);
     336    GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format,
     337                       BindOptions);
     338    GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format,
     339                       BindOptions);
    306340
    307341    void deleteTexture(QMacCompatGLuint tx_id);
     
    349383
    350384private:
    351     QGLContextPrivate* d_ptr;
     385    QScopedPointer<QGLContextPrivate> d_ptr;
    352386
    353387    friend class QGLPixelBuffer;
    354388    friend class QGLPixelBufferPrivate;
    355389    friend class QGLWidget;
    356     friend class QGLDrawable;
    357390    friend class QGLWidgetPrivate;
    358391    friend class QGLGlyphCache;
     
    364397    friend class QGLPixmapData;
    365398    friend class QGLPixmapFilterBase;
     399    friend class QGLTextureGlyphCache;
     400    friend class QGLShareRegister;
     401    friend class QGLSharedResourceGuard;
     402    friend class QGLPixmapBlurFilter;
    366403    friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
    367404#ifdef Q_WS_MAC
     
    372409    friend QGLContextPrivate *qt_phonon_get_dptr(const QGLContext *);
    373410#endif
    374 #ifdef Q_WS_WIN
    375411    friend class QGLFramebufferObject;
    376412    friend class QGLFramebufferObjectPrivate;
    377     friend bool qt_resolve_GLSL_functions(QGLContext *ctx);
    378     friend bool qt_createGLSLProgram(QGLContext *ctx, GLuint &program, const char *shader_src, GLuint &shader);
    379 #endif
     413    friend class QGLFBOGLPaintDevice;
     414    friend class QGLPaintDevice;
     415    friend class QX11GLPixmapData;
    380416private:
    381417    Q_DISABLE_COPY(QGLContext)
    382418};
    383419
     420Q_DECLARE_OPERATORS_FOR_FLAGS(QGLContext::BindOptions)
    384421
    385422class Q_OPENGL_EXPORT QGLWidget : public QWidget
     
    417454    void swapBuffers();
    418455
    419     // ### Qt 5: make format() return a const ref instead
    420456    QGLFormat format() const;
    421457    void setFormat(const QGLFormat& format);
     
    444480    QPaintEngine *paintEngine() const;
    445481
     482    GLuint bindTexture(const QImage &image, GLenum target, GLint format,
     483                       QGLContext::BindOptions options);
     484    GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
     485                       QGLContext::BindOptions options);
     486
    446487    GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
    447488                       GLint format = GL_RGBA);
    448489    GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
    449490                       GLint format = GL_RGBA);
     491
    450492    GLuint bindTexture(const QString &fileName);
    451493
     
    460502    GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum = GL_TEXTURE_2D,
    461503                       QMacCompatGLint format = GL_RGBA);
     504    GLuint bindTexture(const QImage &image, QMacCompatGLenum, QMacCompatGLint format,
     505                       QGLContext::BindOptions);
     506    GLuint bindTexture(const QPixmap &pixmap, QMacCompatGLenum, QMacCompatGLint format,
     507                       QGLContext::BindOptions);
    462508
    463509    void deleteTexture(QMacCompatGLuint tx_id);
     
    501547    friend class QGLPixelBufferPrivate;
    502548    friend class QGLContext;
     549    friend class QGLContextPrivate;
    503550    friend class QGLOverlayWidget;
    504551    friend class QOpenGLPaintEngine;
     552    friend class QGLPaintDevice;
     553    friend class QGLWidgetGLPaintDevice;
    505554};
    506555
  • trunk/src/opengl/qgl_cl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5858inline void glTexParameterf (GLenum target, GLenum pname, GLfloat param)
    5959{
    60     glTexParameterx(target, pname, param);
     60    glTexParameterx(target, pname, FLOAT2X(param));
    6161}
    6262inline void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  • trunk/src/opengl/qgl_egl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242#include <QtOpenGL/qgl.h>
     43#include "qgl_p.h"
    4344#include "qgl_egl_p.h"
    4445
     
    5859    // if the system hasn't already chosen a fixed format to
    5960    // match the pixmap, widget, etc.
    60     if (props.value(EGL_RED_SIZE) == EGL_DONT_CARE || f.redBufferSize() != -1)
     61    if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1)
    6162        props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize());
    62     if (props.value(EGL_GREEN_SIZE) == EGL_DONT_CARE || f.greenBufferSize() != -1)
     63    if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1)
    6364        props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize());
    64     if (props.value(EGL_BLUE_SIZE) == EGL_DONT_CARE || f.blueBufferSize() != -1)
     65    if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1)
    6566        props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize());
    6667    if (f.alpha()) {
    67         if (props.value(EGL_ALPHA_SIZE) == EGL_DONT_CARE || f.alphaBufferSize() != -1)
     68        if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1)
    6869            props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize());
    6970    }
     
    7576    if (f.sampleBuffers()) {
    7677        props.setValue(EGL_SAMPLE_BUFFERS, 1);
    77         props.setValue(EGL_SAMPLES, f.samples());
     78        props.setValue(EGL_SAMPLES, f.samples() == -1 ? 1 : f.samples());
    7879    } else {
    7980        props.setValue(EGL_SAMPLE_BUFFERS, 0);
     
    129130}
    130131
     132bool QGLFormat::hasOpenGL()
     133{
     134    return true;
     135}
     136
     137void QGLContext::reset()
     138{
     139    Q_D(QGLContext);
     140    if (!d->valid)
     141        return;
     142    d->cleanup();
     143    doneCurrent();
     144    if (d->eglContext) {
     145        d->destroyEglSurfaceForDevice();
     146        delete d->eglContext;
     147    }
     148    d->eglContext = 0;
     149    d->eglSurface = EGL_NO_SURFACE;
     150    d->crWin = false;
     151    d->sharing = false;
     152    d->valid = false;
     153    d->transpColor = QColor();
     154    d->initDone = false;
     155    qgl_share_reg()->removeShare(this);
     156}
     157
     158void QGLContext::makeCurrent()
     159{
     160    Q_D(QGLContext);
     161    if (!d->valid || !d->eglContext || d->eglSurface == EGL_NO_SURFACE) {
     162        qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
     163        return;
     164    }
     165
     166    if (d->eglContext->makeCurrent(d->eglSurface))
     167        QGLContextPrivate::setCurrentContext(this);
     168}
     169
     170void QGLContext::doneCurrent()
     171{
     172    Q_D(QGLContext);
     173    if (d->eglContext)
     174        d->eglContext->doneCurrent();
     175
     176    QGLContextPrivate::setCurrentContext(0);
     177}
     178
     179
     180void QGLContext::swapBuffers() const
     181{
     182    Q_D(const QGLContext);
     183    if (!d->valid || !d->eglContext)
     184        return;
     185
     186    d->eglContext->swapBuffers(d->eglSurface);
     187}
     188
     189void QGLContextPrivate::destroyEglSurfaceForDevice()
     190{
     191    if (eglSurface != EGL_NO_SURFACE) {
     192#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
     203#endif
     204            eglDestroySurface(eglContext->display(), eglSurface);
     205        eglSurface = EGL_NO_SURFACE;
     206    }
     207}
     208
     209void QGLWidget::setMouseTracking(bool enable)
     210{
     211    QWidget::setMouseTracking(enable);
     212}
     213
     214QColor QGLContext::overlayTransparentColor() const
     215{
     216    return d_func()->transpColor;
     217}
     218
     219uint QGLContext::colorIndex(const QColor &c) const
     220{
     221    Q_UNUSED(c);
     222    return 0;
     223}
     224
     225void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
     226{
     227    Q_UNUSED(fnt);
     228    Q_UNUSED(listBase);
     229}
     230
     231void *QGLContext::getProcAddress(const QString &proc) const
     232{
     233    return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));
     234}
     235
     236bool QGLWidgetPrivate::renderCxPm(QPixmap*)
     237{
     238    return false;
     239}
     240
    131241QT_END_NAMESPACE
  • trunk/src/opengl/qgl_egl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5454//
    5555
    56 #include "qegl_p.h"
     56#include <QtGui/private/qegl_p.h>
    5757
    5858QT_BEGIN_NAMESPACE
  • trunk/src/opengl/qgl_mac.mm

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    461461        aglDestroyContext((AGLContext)d->cx);
    462462#else
     463    QMacCocoaAutoReleasePool pool;
    463464    [static_cast<NSOpenGLContext *>(d->cx) release];
    464465#endif
     
    494495    [static_cast<NSOpenGLContext *>(d->cx) makeCurrentContext];
    495496#endif
    496     currentCtx = this;
    497     if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
    498         qgl_context_storage.setLocalData(new QGLThreadContext);
    499     if (qgl_context_storage.hasLocalData())
    500         qgl_context_storage.localData()->context = this;
     497    QGLContextPrivate::setCurrentContext(this);
    501498}
    502499
     
    657654        return;
    658655
    659     currentCtx = 0;
    660     if (qgl_context_storage.hasLocalData())
    661         qgl_context_storage.localData()->context = 0;
     656    QGLContextPrivate::setCurrentContext(0);
    662657#ifndef QT_MAC_USE_COCOA
    663658    aglSetCurrentContext(0);
  • trunk/src/opengl/qgl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6060#include "QtCore/qthreadstorage.h"
    6161#include "QtCore/qhash.h"
     62#include "QtCore/qatomic.h"
    6263#include "private/qwidget_p.h"
     64#include "qcache.h"
     65#include "qglpaintdevice_p.h"
    6366
    6467#ifndef QT_OPENGL_ES_1_CL
     
    127130{
    128131public:
    129     QGLFormatPrivate() {
     132    QGLFormatPrivate()
     133        : ref(1)
     134    {
    130135        opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer;
    131 #if defined(QT_OPENGL_ES_2)
    132         opts |= QGL::SampleBuffers;
    133 #endif
    134136        pln = 0;
    135137        depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
     
    137139        swapInterval = -1;
    138140    }
     141    QGLFormatPrivate(const QGLFormatPrivate *other)
     142        : ref(1),
     143          opts(other->opts),
     144          pln(other->pln),
     145          depthSize(other->depthSize),
     146          accumSize(other->accumSize),
     147          stencilSize(other->stencilSize),
     148          redSize(other->redSize),
     149          greenSize(other->greenSize),
     150          blueSize(other->blueSize),
     151          alphaSize(other->alphaSize),
     152          numSamples(other->numSamples),
     153          swapInterval(other->swapInterval)
     154    {
     155    }
     156    QAtomicInt ref;
    139157    QGL::FormatOptions opts;
    140158    int pln;
     
    155173public:
    156174    QGLWidgetPrivate() : QWidgetPrivate()
     175                       , disable_clear_on_painter_begin(false)
    157176#ifdef Q_WS_QWS
    158177                       , wsurf(0)
     
    171190
    172191    QGLContext *glcx;
     192    QGLWidgetGLPaintDevice glDevice;
    173193    bool autoSwap;
    174194
    175195    QGLColormap cmap;
     196#ifndef QT_OPENGL_ES
    176197    QMap<QString, int> displayListCache;
     198#endif
     199
     200    bool disable_clear_on_painter_begin;
    177201
    178202#if defined(Q_WS_WIN)
     
    193217};
    194218
     219class QGLContextResource;
     220class QGLSharedResourceGuard;
     221
     222typedef QHash<QString, GLuint> QGLDDSCache;
     223
     224// QGLContextPrivate has the responsibility of creating context groups.
     225// QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy
     226// context groups when needed.
     227// QGLShareRegister has the responsibility of keeping the context pointer up to date.
     228class QGLContextGroup
     229{
     230public:
     231    ~QGLContextGroup();
     232
     233    QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
     234    const QGLContext *context() const {return m_context;}
     235    bool isSharing() const { return m_shares.size() >= 2; }
     236
     237    void addGuard(QGLSharedResourceGuard *guard);
     238    void removeGuard(QGLSharedResourceGuard *guard);
     239private:
     240    QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
     241
     242    QGLExtensionFuncs m_extensionFuncs;
     243    const QGLContext *m_context; // context group's representative
     244    QList<const QGLContext *> m_shares;
     245    QHash<QGLContextResource *, void *> m_resources;
     246    QGLSharedResourceGuard *m_guards; // double-linked list of active guards.
     247    QAtomicInt m_refs;
     248    QGLDDSCache m_dds_cache;
     249
     250    void cleanupResources(const QGLContext *ctx);
     251
     252    friend class QGLShareRegister;
     253    friend class QGLContext;
     254    friend class QGLContextPrivate;
     255    friend class QGLContextResource;
     256};
     257
     258class QGLTexture;
     259
    195260class QGLContextPrivate
    196261{
    197262    Q_DECLARE_PUBLIC(QGLContext)
    198263public:
    199     explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {}
    200     ~QGLContextPrivate() {}
    201     GLuint bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
    202                        bool clean = false);
    203     GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean);
    204     GLuint bindTexture(const QImage &image, GLenum target, GLint format, bool clean);
    205     bool textureCacheLookup(const qint64 key, GLenum target, GLuint *id);
     264    explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
     265    ~QGLContextPrivate();
     266    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
     267                            QGLContext::BindOptions options);
     268    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
     269                            QGLContext::BindOptions options);
     270    QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
     271                            QGLContext::BindOptions options);
     272    QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
    206273    void init(QPaintDevice *dev, const QGLFormat &format);
    207274    QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
     
    221288#if defined(QT_OPENGL_ES)
    222289    QEglContext *eglContext;
     290    EGLSurface eglSurface;
     291    void destroyEglSurfaceForDevice();
    223292#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
    224293    void* cx;
     
    231300    quint32 gpm;
    232301    int screen;
     302    QHash<QPixmapData*, QPixmap> boundPixmaps;
     303    QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
     304                                            QGLContext::BindOptions options);
     305    static void destroyGlSurfaceForPixmap(QPixmapData*);
     306    static void unbindPixmapFromTexture(QPixmapData*);
    233307#endif
    234308#if defined(Q_WS_MAC)
     
    239313    QGLFormat glFormat;
    240314    QGLFormat reqFormat;
    241     GLuint pbo;
     315    GLuint fbo;
    242316
    243317    uint valid : 1;
     
    245319    uint initDone : 1;
    246320    uint crWin : 1;
    247     uint clear_on_painter_begin : 1;
    248321    uint internal_context : 1;
    249322    uint version_flags_cached : 1;
     
    253326    QGLFormat::OpenGLVersionFlags version_flags;
    254327
    255     QGLExtensionFuncs extensionFuncs;
     328    QGLContextGroup *group;
    256329    GLint max_texture_size;
    257330
     331    GLuint current_fbo;
     332    GLuint default_fbo;
     333    QPaintEngine *active_engine;
     334
     335    static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
     336
    258337#ifdef Q_WS_WIN
    259     static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; }
     338    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
    260339#endif
    261340
    262341#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
    263342    static QGLExtensionFuncs qt_extensionFuncs;
    264     static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *) { return qt_extensionFuncs; }
    265 #endif
    266 
    267     QPixmapFilter *createPixmapFilter(int type) const;
     343    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
     344#endif
     345
     346    static void setCurrentContext(QGLContext *context);
    268347};
    269348
    270349// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
    271 class QGLSignalProxy : public QObject
     350class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
    272351{
    273352    Q_OBJECT
     
    297376        PackedDepthStencil      = 0x00000200,
    298377        NVFloatBuffer           = 0x00000400,
    299         PixelBufferObject       = 0x00000800
     378        PixelBufferObject       = 0x00000800,
     379        FramebufferBlit         = 0x00001000,
     380        NPOTTextures            = 0x00002000,
     381        BGRATextureFormat       = 0x00004000,
     382        DDSTextureCompression   = 0x00008000,
     383        ETC1TextureCompression  = 0x00010000,
     384        PVRTCTextureCompression = 0x00020000,
     385        FragmentShader          = 0x00040000
    300386    };
    301387    Q_DECLARE_FLAGS(Extensions, Extension)
     
    310396
    311397
    312 struct QGLThreadContext {
     398class Q_OPENGL_EXPORT QGLShareRegister
     399{
     400public:
     401    QGLShareRegister() {}
     402    ~QGLShareRegister() {}
     403
     404    void addShare(const QGLContext *context, const QGLContext *share);
     405    QList<const QGLContext *> shares(const QGLContext *context);
     406    void removeShare(const QGLContext *context);
     407};
     408
     409extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
     410
     411// Temporarily make a context current if not already current or
     412// shared with the current contex.  The previous context is made
     413// current when the object goes out of scope.
     414class Q_OPENGL_EXPORT QGLShareContextScope
     415{
     416public:
     417    QGLShareContextScope(const QGLContext *ctx)
     418        : m_oldContext(0)
     419    {
     420        QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
     421        if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
     422            m_oldContext = currentContext;
     423            m_ctx = const_cast<QGLContext *>(ctx);
     424            m_ctx->makeCurrent();
     425        } else {
     426            m_ctx = currentContext;
     427        }
     428    }
     429
     430    operator QGLContext *()
     431    {
     432        return m_ctx;
     433    }
     434
     435    QGLContext *operator->()
     436    {
     437        return m_ctx;
     438    }
     439
     440    ~QGLShareContextScope()
     441    {
     442        if (m_oldContext)
     443            m_oldContext->makeCurrent();
     444    }
     445
     446private:
     447    QGLContext *m_oldContext;
     448    QGLContext *m_ctx;
     449};
     450
     451class QGLTexture {
     452public:
     453    QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
     454               QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
     455        : context(ctx),
     456          id(tx_id),
     457          target(tx_target),
     458          options(opt)
     459#if defined(Q_WS_X11)
     460        , boundPixmap(0)
     461#endif
     462    {}
     463
     464    ~QGLTexture() {
     465        if (options & QGLContext::MemoryManagedBindOption) {
     466            Q_ASSERT(context);
     467            QGLShareContextScope scope(context);
     468#if defined(Q_WS_X11)
     469            // Although glXReleaseTexImage is a glX call, it must be called while there
     470            // is a current context - the context the pixmap was bound to a texture in.
     471            // Otherwise the release doesn't do anything and you get BadDrawable errors
     472            // when you come to delete the context.
     473            if (boundPixmap)
     474                QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
     475#endif
     476            glDeleteTextures(1, &id);
     477        }
     478     }
     479
    313480    QGLContext *context;
    314 };
    315 extern QThreadStorage<QGLThreadContext *> qgl_context_storage;
    316 
    317 typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash;
    318 class QGLShareRegister
    319 {
    320 public:
    321     QGLShareRegister() {}
    322     ~QGLShareRegister() { reg.clear(); }
    323 
    324     bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) {
    325         if (context1 == context2)
    326             return true;
    327         QList<const QGLContext *> shares = reg.values(context1);
    328         for (int k=0; k<shares.size(); ++k) {
    329             const QGLContext *ctx = shares.at(k);
    330             if (ctx == skip) // avoid an indirect circular loop (infinite recursion)
    331                 continue;
    332             if (ctx == context2)
     481    GLuint id;
     482    GLenum target;
     483
     484    QGLContext::BindOptions options;
     485
     486#if defined(Q_WS_X11)
     487    QPixmapData* boundPixmap;
     488#endif
     489
     490    bool canBindCompressedTexture
     491        (const char *buf, int len, const char *format, bool *hasAlpha);
     492    QSize bindCompressedTexture
     493        (const QString& fileName, const char *format = 0);
     494    QSize bindCompressedTexture
     495        (const char *buf, int len, const char *format = 0);
     496    QSize bindCompressedTextureDDS(const char *buf, int len);
     497    QSize bindCompressedTexturePVR(const char *buf, int len);
     498};
     499
     500class QGLTextureCache {
     501public:
     502    QGLTextureCache();
     503    ~QGLTextureCache();
     504
     505    void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
     506    void remove(quint64 key) { m_cache.remove(key); }
     507    bool remove(QGLContext *ctx, GLuint textureId);
     508    void removeContextTextures(QGLContext *ctx);
     509    int size() { return m_cache.size(); }
     510    void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); }
     511    int maxCost() {return m_cache.maxCost(); }
     512    QGLTexture* getTexture(quint64 key) { return m_cache.object(key); }
     513
     514    static QGLTextureCache *instance();
     515    static void deleteIfEmpty();
     516    static void imageCleanupHook(qint64 cacheKey);
     517    static void cleanupTextures(QPixmap* pixmap);
     518#ifdef Q_WS_X11
     519    // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces
     520    static void cleanupPixmapSurfaces(QPixmap* pixmap);
     521#endif
     522
     523private:
     524    QCache<qint64, QGLTexture> m_cache;
     525};
     526
     527
     528extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine();
     529
     530bool qt_gl_preferGL2Engine();
     531
     532inline GLenum qt_gl_preferredTextureFormat()
     533{
     534    return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
     535        ? GL_BGRA : GL_RGBA;
     536}
     537
     538inline GLenum qt_gl_preferredTextureTarget()
     539{
     540#if defined(QT_OPENGL_ES_2)
     541    return GL_TEXTURE_2D;
     542#else
     543    return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
     544           && !qt_gl_preferGL2Engine()
     545           ? GL_TEXTURE_RECTANGLE_NV
     546           : GL_TEXTURE_2D;
     547#endif
     548}
     549
     550// One resource per group of shared contexts.
     551class Q_AUTOTEST_EXPORT QGLContextResource
     552{
     553public:
     554    typedef void (*FreeFunc)(void *);
     555    QGLContextResource(FreeFunc f);
     556    ~QGLContextResource();
     557    // Set resource 'value' for 'key' and all its shared contexts.
     558    void insert(const QGLContext *key, void *value);
     559    // Return resource for 'key' or a shared context.
     560    void *value(const QGLContext *key);
     561    // Cleanup 'value' in response to a context group being destroyed.
     562    void cleanup(const QGLContext *ctx, void *value);
     563private:
     564    FreeFunc free;
     565    QAtomicInt active;
     566};
     567
     568// Put a guard around a GL object identifier and its context.
     569// When the context goes away, a shared context will be used
     570// in its place.  If there are no more shared contexts, then
     571// the identifier is returned as zero - it is assumed that the
     572// context destruction cleaned up the identifier in this case.
     573class Q_OPENGL_EXPORT QGLSharedResourceGuard
     574{
     575public:
     576    QGLSharedResourceGuard(const QGLContext *context)
     577        : m_group(0), m_id(0), m_next(0), m_prev(0)
     578    {
     579        setContext(context);
     580    }
     581    QGLSharedResourceGuard(const QGLContext *context, GLuint id)
     582        : m_group(0), m_id(id), m_next(0), m_prev(0)
     583    {
     584        setContext(context);
     585    }
     586    ~QGLSharedResourceGuard();
     587
     588    const QGLContext *context() const
     589    {
     590        return m_group ? m_group->context() : 0;
     591    }
     592
     593    void setContext(const QGLContext *context);
     594
     595    GLuint id() const
     596    {
     597        return m_id;
     598    }
     599
     600    void setId(GLuint id)
     601    {
     602        m_id = id;
     603    }
     604
     605private:
     606    QGLContextGroup *m_group;
     607    GLuint m_id;
     608    QGLSharedResourceGuard *m_next;
     609    QGLSharedResourceGuard *m_prev;
     610
     611    friend class QGLContextGroup;
     612};
     613
     614
     615// This class can be used to match GL extensions with doing any mallocs. The
     616// class assumes that the GL extension string ends with a space character,
     617// which it should do on all conformant platforms. Create the object and pass
     618// in a pointer to the extension string, then call match() on each extension
     619// that should be matched. The match() function takes the extension name
     620// *without* the terminating space character as input.
     621
     622class QGLExtensionMatcher
     623{
     624public:
     625    QGLExtensionMatcher(const char *str)
     626        : gl_extensions(str), gl_extensions_length(qstrlen(str))
     627    {}
     628
     629    bool match(const char *str) {
     630        int str_length = qstrlen(str);
     631        const char *extensions = gl_extensions;
     632        int extensions_length = gl_extensions_length;
     633
     634        while (1) {
     635            // the total length that needs to be matched is the str_length +
     636            // the space character that terminates the extension name
     637            if (extensions_length < str_length + 1)
     638                return false;
     639            if (qstrncmp(extensions, str, str_length) == 0 && extensions[str_length] == ' ')
    333640                return true;
    334             if (checkSharing(ctx, context2, context1))
    335                 return true;
     641
     642            int split_pos = 0;
     643            while (split_pos < extensions_length && extensions[split_pos] != ' ')
     644                ++split_pos;
     645            ++split_pos; // added for the terminating space character
     646            extensions += split_pos;
     647            extensions_length -= split_pos;
    336648        }
    337649        return false;
    338650    }
    339651
    340     void addShare(const QGLContext *context, const QGLContext *share) {
    341         reg.insert(context, share); // context sharing works both ways
    342         reg.insert(share, context);
    343     }
    344 
    345     void removeShare(const QGLContext *context) {
    346         QGLSharingHash::iterator it = reg.begin();
    347         while (it != reg.end()) {
    348             if (it.key() == context || it.value() == context)
    349                 it = reg.erase(it);
    350             else
    351                 ++it;
    352         }
    353     }
    354 
    355     void replaceShare(const QGLContext *oldContext, const QGLContext *newContext) {
    356         QGLSharingHash::iterator it = reg.begin();
    357         while (it != reg.end()) {
    358             if (it.key() == oldContext)
    359                 reg.insert(newContext, it.value());
    360             else if (it.value() == oldContext)
    361                 reg.insert(it.key(), newContext);
    362             ++it;
    363         }
    364         removeShare(oldContext);
    365     }
    366 
    367652private:
    368     QGLSharingHash reg;
    369 };
    370 
    371 extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
    372 
    373 #ifdef Q_WS_QWS
    374 class QOpenGLPaintEngine;
    375 extern QOpenGLPaintEngine* qt_qgl_paint_engine();
    376 
    377 extern EGLDisplay qt_qgl_egl_display();
    378 #endif
    379 
    380 inline GLenum qt_gl_preferredTextureFormat()
    381 {
    382     return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA;
    383 }
    384 
    385 inline GLenum qt_gl_preferredTextureTarget()
    386 {
    387     return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
    388            ? GL_TEXTURE_RECTANGLE_NV
    389            : GL_TEXTURE_2D;
    390 }
    391 
     653    const char *gl_extensions;
     654    int gl_extensions_length;
     655};
    392656
    393657QT_END_NAMESPACE
  • trunk/src/opengl/qgl_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5252#include <qcolor.h>
    5353
    54 #include <windows.h>
     54#include <qt_windows.h>
    5555
    5656typedef bool (APIENTRY *PFNWGLGETPIXELFORMATATTRIBIVARB)(HDC hdc,
     
    643643        if (parent && !parent->internalWinId())
    644644            parent = parent->nativeParentWidget();
    645         QT_WA({
    646             const TCHAR *cname = (TCHAR*)windowClassName.utf16();
    647             dmy_id = CreateWindow(cname, 0, 0, 0, 0, 1, 1,
    648                                   parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
    649         } , {
    650             dmy_id = CreateWindowA(windowClassName.toLatin1(), 0, 0, 0, 0, 1, 1,
    651                                    parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
    652         });
     645
     646        dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
     647                              0, 0, 0, 0, 1, 1,
     648                              parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
    653649
    654650        dmy_pdc = GetDC(dmy_id);
     
    665661        SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd);
    666662        dmy_rc = wglCreateContext(dmy_pdc);
     663        old_dc = wglGetCurrentDC();
     664        old_context = wglGetCurrentContext();
    667665        wglMakeCurrent(dmy_pdc, dmy_rc);
    668666    }
     
    673671        ReleaseDC(dmy_id, dmy_pdc);
    674672        DestroyWindow(dmy_id);
     673        if (old_dc && old_context)
     674            wglMakeCurrent(old_dc, old_context);
    675675    }
    676676
    677677    HDC dmy_pdc;
    678678    HGLRC dmy_rc;
     679    HDC old_dc;
     680    HGLRC old_context;
    679681    WId dmy_id;
    680682};
     
    885887}
    886888
    887 /*!
    888     \bold{Win32 only:} This virtual function chooses a pixel
    889     format that matches the OpenGL \link setFormat() format\endlink.
    890     Reimplement this function in a subclass if you need a custom
    891     context.
    892 
    893     \warning The \a dummyPfd pointer and \a pdc are used as a \c
    894     PIXELFORMATDESCRIPTOR*. We use \c void to avoid using
    895     Windows-specific types in our header files.
    896 
    897     \sa chooseContext()
    898 */
    899 
     889/*
     890  See qgl.cpp for qdoc comment.
     891 */
    900892int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
    901893{
     
    11881180
    11891181    if (wglMakeCurrent(d->dc, d->rc)) {
    1190         if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
    1191             qgl_context_storage.setLocalData(new QGLThreadContext);
    1192         if (qgl_context_storage.hasLocalData())
    1193             qgl_context_storage.localData()->context = this;
    1194         currentCtx = this;
     1182        QGLContextPrivate::setCurrentContext(this);
    11951183    } else {
    11961184        qwglError("QGLContext::makeCurrent()", "wglMakeCurrent");
     
    12021190{
    12031191    Q_D(QGLContext);
    1204     currentCtx = 0;
    12051192    wglMakeCurrent(0, 0);
    1206     if (qgl_context_storage.hasLocalData())
    1207         qgl_context_storage.localData()->context = 0;
     1193    QGLContextPrivate::setCurrentContext(0);
    12081194    if (deviceIsPixmap() && d->hbitmap) {
    12091195        QPixmap *pm = static_cast<QPixmap *>(d->paintDevice);
     
    14281414
    14291415    if (!d->glcx->isValid()) {
    1430         bool wasSharing = shareContext || oldcx && oldcx->isSharing();
     1416        bool wasSharing = shareContext || (oldcx && oldcx->isSharing());
    14311417        d->glcx->create(shareContext ? shareContext : oldcx);
    14321418        // the above is a trick to keep disp lists etc when a
  • trunk/src/opengl/qgl_x11.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353#include <private/qfontengine_ft_p.h>
    5454#include <private/qt_x11_p.h>
     55#include <private/qpixmap_x11_p.h>
     56#include <private/qimagepixmapcleanuphooks_p.h>
    5557#ifdef Q_OS_HPUX
    5658// for GLXPBuffer
    5759#include <private/qglpixelbuffer_p.h>
    5860#endif
     61
     62// We always define GLX_EXT_texture_from_pixmap ourselves because
     63// we can't trust system headers to do it properly
     64#define GLX_EXT_texture_from_pixmap 1
    5965
    6066#define INT8  dummy_INT8
     
    6369#undef  INT8
    6470#undef  INT32
     71
    6572#include <X11/Xlib.h>
    6673#include <X11/Xutil.h>
    6774#include <X11/Xos.h>
     75#ifdef Q_OS_VXWORS
     76#  ifdef open
     77#    undef open
     78#  endif
     79#  ifdef getpid
     80#    undef getpid
     81#  endif
     82#endif // Q_OS_VXWORKS
    6883#include <X11/Xatom.h>
    6984
     
    8095#define GLX_SAMPLE_BUFFERS_ARB  100000
    8196#define GLX_SAMPLES_ARB         100001
     97#endif
     98
     99#ifndef GLX_TEXTURE_2D_BIT_EXT
     100#define GLX_TEXTURE_2D_BIT_EXT             0x00000002
     101#define GLX_TEXTURE_RECTANGLE_BIT_EXT      0x00000004
     102#define GLX_BIND_TO_TEXTURE_RGB_EXT        0x20D0
     103#define GLX_BIND_TO_TEXTURE_RGBA_EXT       0x20D1
     104#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT     0x20D2
     105#define GLX_BIND_TO_TEXTURE_TARGETS_EXT    0x20D3
     106#define GLX_Y_INVERTED_EXT                 0x20D4
     107#define GLX_TEXTURE_FORMAT_EXT             0x20D5
     108#define GLX_TEXTURE_TARGET_EXT             0x20D6
     109#define GLX_MIPMAP_TEXTURE_EXT             0x20D7
     110#define GLX_TEXTURE_FORMAT_NONE_EXT        0x20D8
     111#define GLX_TEXTURE_FORMAT_RGB_EXT         0x20D9
     112#define GLX_TEXTURE_FORMAT_RGBA_EXT        0x20DA
     113#define GLX_TEXTURE_2D_EXT                 0x20DC
     114#define GLX_TEXTURE_RECTANGLE_EXT          0x20DD
     115#define GLX_FRONT_LEFT_EXT                 0x20DE
    82116#endif
    83117
     
    130164    GLCMapHash *qglcmap_hash;
    131165};
    132 Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler);
     166Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler)
    133167
    134168static void cleanup_cmaps()
     
    298332  QGLFormat UNIX/GLX-specific code
    299333 *****************************************************************************/
     334
     335void* qglx_getProcAddress(const char* procName)
     336{
     337    // On systems where the GL driver is pluggable (like Mesa), we have to use
     338    // the glXGetProcAddressARB extension to resolve other function pointers as
     339    // the symbols wont be in the GL library, but rather in a plugin loaded by
     340    // the GL library.
     341    typedef void* (*qt_glXGetProcAddressARB)(const char *);
     342    static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
     343    static bool triedResolvingGlxGetProcAddress = false;
     344    if (!triedResolvingGlxGetProcAddress) {
     345        triedResolvingGlxGetProcAddress = true;
     346        QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
     347        if (extensions.match("GLX_ARB_get_proc_address")) {
     348#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
     349            void *handle = dlopen(NULL, RTLD_LAZY);
     350            if (handle) {
     351                glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
     352                dlclose(handle);
     353            }
     354            if (!glXGetProcAddressARB)
     355#endif
     356            {
     357#if !defined(QT_NO_LIBRARY)
     358                extern const QString qt_gl_library_name();
     359                QLibrary lib(qt_gl_library_name());
     360                glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
     361#endif
     362            }
     363        }
     364    }
     365
     366    void *procAddress = 0;
     367    if (glXGetProcAddressARB)
     368        procAddress = glXGetProcAddressARB(procName);
     369
     370    // If glXGetProcAddress didn't work, try looking the symbol up in the GL library
     371#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
     372    if (!procAddress) {
     373        void *handle = dlopen(NULL, RTLD_LAZY);
     374        if (handle) {
     375            procAddress = dlsym(handle, procName);
     376            dlclose(handle);
     377        }
     378    }
     379#endif
     380#if !defined(QT_NO_LIBRARY)
     381    if (!procAddress) {
     382        extern const QString qt_gl_library_name();
     383        QLibrary lib(qt_gl_library_name());
     384        procAddress = lib.resolve(procName);
     385    }
     386#endif
     387
     388    return procAddress;
     389}
    300390
    301391bool QGLFormat::hasOpenGL()
     
    434524            return false;
    435525    }
    436     QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
    437     if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
     526    QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
     527    if (extensions.match("GLX_SGI_video_sync")) {
    438528        if (d->glFormat.swapInterval() == -1)
    439529            d->glFormat.setSwapInterval(0);
     
    444534}
    445535
    446 
    447 /*!
    448   \bold{X11 only:} This virtual function tries to find a
    449   visual that matches the format, reducing the demands if the original
    450   request cannot be met.
    451 
    452   The algorithm for reducing the demands of the format is quite
    453   simple-minded, so override this method in your subclass if your
    454   application has spcific requirements on visual selection.
    455 
    456   \sa chooseContext()
    457 */
    458 
     536/*
     537  See qgl.cpp for qdoc comment.
     538 */
    459539void *QGLContext::chooseVisual()
    460540{
     
    520600}
    521601
    522 
    523 /*!
    524   \internal
    525 
    526   \bold{X11 only:} This virtual function chooses a visual
    527   that matches the OpenGL \link format() format\endlink. Reimplement this
    528   function in a subclass if you need a custom visual.
    529 
    530   \sa chooseContext()
    531 */
    532 
     602/*
     603  See qgl.cpp for qdoc comment.
     604 */
    533605void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
    534606{
    535607    Q_D(QGLContext);
    536     int spec[40];
     608    int spec[45];
    537609    int i = 0;
    538610    spec[i++] = GLX_LEVEL;
    539611    spec[i++] = f.plane();
    540612    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
    541628
    542629#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
     
    544631    static bool useTranspExtChecked = false;
    545632    if (f.plane() && !useTranspExtChecked && d->paintDevice) {
    546         QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
    547         useTranspExt = estr.contains("GLX_EXT_visual_info");
     633        QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
     634        useTranspExt = extensions.match("GLX_EXT_visual_info");
    548635        //# (A bit simplistic; that could theoretically be a substring)
    549636        if (useTranspExt) {
     
    566653        useTranspExtChecked = true;
    567654    }
    568     if (f.plane() && useTranspExt) {
     655    if (f.plane() && useTranspExt && !useFBConfig) {
    569656        // Required to avoid non-transparent overlay visual(!) on some systems
    570657        spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
     
    573660#endif
    574661
     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
    575670    if (f.doubleBuffer())
    576671        spec[i++] = GLX_DOUBLEBUFFER;
     672        if (useFBConfig)
     673            spec[i++] = True;
    577674    if (f.depth()) {
    578675        spec[i++] = GLX_DEPTH_SIZE;
     
    581678    if (f.stereo()) {
    582679        spec[i++] = GLX_STEREO;
     680        if (useFBConfig)
     681            spec[i++] = True;
    583682    }
    584683    if (f.stencil()) {
     
    587686    }
    588687    if (f.rgba()) {
    589         spec[i++] = GLX_RGBA;
     688        if (!useFBConfig)
     689            spec[i++] = GLX_RGBA;
    590690        spec[i++] = GLX_RED_SIZE;
    591691        spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
     
    622722    }
    623723
     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
    624744    spec[i] = XNone;
    625     return glXChooseVisual(xinfo->display(), xinfo->screen(), spec);
     745
     746
     747    XVisualInfo* chosenVisualInfo = 0;
     748
     749#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     750    while (useFBConfig) {
     751        GLXFBConfig *configs;
     752        int configCount = 0;
     753        configs = glXChooseFBConfig(xinfo->display(), xinfo->screen(), spec, &configCount);
     754
     755        if (!configs)
     756            break; // fallback to trying glXChooseVisual
     757
     758        for (i = 0; i < configCount; ++i) {
     759            XVisualInfo* vi;
     760            vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]);
     761            if (!vi)
     762                continue;
     763
     764#if !defined(QT_NO_XRENDER)
     765            QWidget* w = 0;
     766            if (d->paintDevice->devType() == QInternal::Widget)
     767                w = static_cast<QWidget*>(d->paintDevice);
     768
     769            if (w && w->testAttribute(Qt::WA_TranslucentBackground) && f.alpha()) {
     770                // Attempt to find a config who's visual has a proper alpha channel
     771                XRenderPictFormat *pictFormat;
     772                pictFormat = XRenderFindVisualFormat(xinfo->display(), vi->visual);
     773
     774                if (pictFormat && (pictFormat->type == PictTypeDirect) && pictFormat->direct.alphaMask) {
     775                    // The pict format for the visual matching the FBConfig indicates ARGB
     776                    if (chosenVisualInfo)
     777                        XFree(chosenVisualInfo);
     778                    chosenVisualInfo = vi;
     779                    break;
     780                }
     781            } else
     782#endif //QT_NO_XRENDER
     783            if (chosenVisualInfo) {
     784                // If we've got a visual we can use and we're not trying to find one with a
     785                // real alpha channel, we might as well just use the one we've got
     786                break;
     787            }
     788
     789            if (!chosenVisualInfo)
     790                chosenVisualInfo = vi; // Have something to fall back to
     791            else
     792                XFree(vi);
     793        }
     794
     795        XFree(configs);
     796        break;
     797    }
     798#endif // defined(GLX_VERSION_1_3)
     799
     800    if (!chosenVisualInfo)
     801        chosenVisualInfo = glXChooseVisual(xinfo->display(), xinfo->screen(), spec);
     802
     803    return chosenVisualInfo;
    626804}
    627805
     
    671849        qWarning("QGLContext::makeCurrent(): Failed.");
    672850
    673     if (ok) {
    674         if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
    675             qgl_context_storage.setLocalData(new QGLThreadContext);
    676         if (qgl_context_storage.hasLocalData())
    677             qgl_context_storage.localData()->context = this;
    678         currentCtx = this;
    679     }
     851    if (ok)
     852        QGLContextPrivate::setCurrentContext(this);
    680853}
    681854
     
    684857    Q_D(QGLContext);
    685858    glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0);
    686     if (qgl_context_storage.hasLocalData())
    687         qgl_context_storage.localData()->context = 0;
    688     currentCtx = 0;
     859    QGLContextPrivate::setCurrentContext(0);
    689860}
    690861
     
    704875            static bool resolved = false;
    705876            if (!resolved) {
    706                 QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
    707                 if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
    708 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
    709                     void *handle = dlopen(NULL, RTLD_LAZY);
    710                     if (handle) {
    711                         glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI) dlsym(handle, "glXGetVideoSyncSGI");
    712                         glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI) dlsym(handle, "glXWaitVideoSyncSGI");
    713                         dlclose(handle);
    714                     }
    715                     if (!glXGetVideoSyncSGI)
    716 #endif
    717                     {
    718                         extern const QString qt_gl_library_name();
    719                         QLibrary lib(qt_gl_library_name());
    720                         glXGetVideoSyncSGI = (qt_glXGetVideoSyncSGI) lib.resolve("glXGetVideoSyncSGI");
    721                         glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI) lib.resolve("glXWaitVideoSyncSGI");
    722                     }
     877                const QX11Info *xinfo = qt_x11Info(d->paintDevice);
     878                QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
     879                if (extensions.match("GLX_SGI_video_sync")) {
     880                    glXGetVideoSyncSGI =  (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI");
     881                    glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI");
    723882                }
    724883                resolved = true;
     
    9491108        return 0;
    9501109    if (!glXGetProcAddressARB) {
    951         QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
    952         if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
     1110        QGLExtensionMatcher extensions(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
     1111        if (extensions.match("GLX_ARB_get_proc_address")) {
    9531112#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
    9541113            void *handle = dlopen(NULL, RTLD_LAZY);
     
    9601119#endif
    9611120            {
     1121#if !defined(QT_NO_LIBRARY)
    9621122                extern const QString qt_gl_library_name();
    9631123                QLibrary lib(qt_gl_library_name());
    9641124                glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
     1125#endif
    9651126            }
    9661127        }
     
    11841345    d->glcx = context;
    11851346
    1186 
    11871347    if (parentWidget()) {
    11881348        // force creation of delay-created widgets
     
    11911351            d_func()->xinfo = parentWidget()->d_func()->xinfo;
    11921352    }
     1353
     1354    // If the application has set WA_TranslucentBackground and not explicitly set
     1355    // the alpha buffer size to zero, modify the format so it have an alpha channel
     1356    QGLFormat& fmt = d->glcx->d_func()->glFormat;
     1357    if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1)
     1358        fmt.setAlphaBufferSize(1);
    11931359
    11941360    bool createFailed = false;
     
    14231589}
    14241590
     1591// Solaris defines glXBindTexImageEXT as part of the GL library
     1592#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     1593typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
     1594typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int);
     1595static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
     1596static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0;
     1597
     1598static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice)
     1599{
     1600    static bool resolvedTextureFromPixmap = false;
     1601
     1602    if (!resolvedTextureFromPixmap) {
     1603        resolvedTextureFromPixmap = true;
     1604
     1605        // Check to see if we have NPOT texture support
     1606        if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
     1607             !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
     1608        {
     1609            return false; // Can't use TFP without NPOT
     1610        }
     1611        const QX11Info *xinfo = qt_x11Info(paintDevice);
     1612        QGLExtensionMatcher extensions(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
     1613        if (extensions.match("GLX_EXT_texture_from_pixmap")) {
     1614            glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT");
     1615            glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT");
     1616        }
     1617    }
     1618
     1619    return glXBindTexImageEXT && glXReleaseTexImageEXT;
     1620}
     1621#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     1622
     1623
     1624QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key,
     1625                                                           QGLContext::BindOptions options)
     1626{
     1627#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
     1628    return 0;
     1629#else
     1630    Q_Q(QGLContext);
     1631
     1632    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     1633
     1634    if (!qt_resolveTextureFromPixmap(paintDevice))
     1635        return 0;
     1636
     1637    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     1638    const QX11Info &x11Info = pixmapData->xinfo;
     1639
     1640    // Store the configs (Can be static because configs aren't dependent on current context)
     1641    static GLXFBConfig glxRGBPixmapConfig = 0;
     1642    static bool RGBConfigInverted = false;
     1643    static GLXFBConfig glxRGBAPixmapConfig = 0;
     1644    static bool RGBAConfigInverted = false;
     1645
     1646    bool hasAlpha = pixmapData->hasAlphaChannel();
     1647
     1648    // Check to see if we need a config
     1649    if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) {
     1650        GLXFBConfig    *configList = 0;
     1651        int             configCount = 0;
     1652
     1653        int configAttribs[] = {
     1654            hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
     1655            GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
     1656            GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
     1657            // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
     1658            GLX_Y_INVERTED_EXT, options & QGLContext::CanFlipNativePixmapBindOption ? GLX_DONT_CARE : False,
     1659            XNone
     1660        };
     1661        configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount);
     1662        if (!configList)
     1663            return 0;
     1664
     1665        int yInv;
     1666        glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv);
     1667
     1668        if (hasAlpha) {
     1669            glxRGBAPixmapConfig = configList[0];
     1670            RGBAConfigInverted = yInv;
     1671        }
     1672        else {
     1673            glxRGBPixmapConfig = configList[0];
     1674            RGBConfigInverted = yInv;
     1675        }
     1676
     1677        XFree(configList);
     1678    }
     1679
     1680    // Check to see if the surface is still valid
     1681    if (pixmapData->gl_surface &&
     1682        hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
     1683    {
     1684        // Surface is invalid!
     1685        destroyGlSurfaceForPixmap(pixmapData);
     1686    }
     1687
     1688    // Check to see if we need a surface
     1689    if (!pixmapData->gl_surface) {
     1690        GLXPixmap glxPixmap;
     1691        int pixmapAttribs[] = {
     1692            GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
     1693            GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
     1694            GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care
     1695            XNone
     1696        };
     1697
     1698        // Wrap the X Pixmap into a GLXPixmap:
     1699        glxPixmap = glXCreatePixmap(x11Info.display(),
     1700                                    hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig,
     1701                                    pixmapData->handle(), pixmapAttribs);
     1702
     1703        if (!glxPixmap)
     1704            return 0;
     1705
     1706        pixmapData->gl_surface = (Qt::HANDLE)glxPixmap;
     1707
     1708        // Make sure the cleanup hook gets called so we can delete the glx pixmap
     1709        QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData);
     1710    }
     1711
     1712    GLuint textureId;
     1713    glGenTextures(1, &textureId);
     1714    glBindTexture(GL_TEXTURE_2D, textureId);
     1715    glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0);
     1716
     1717    glBindTexture(GL_TEXTURE_2D, textureId);
     1718
     1719    if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted)))
     1720        options &= ~QGLContext::InvertedYBindOption;
     1721
     1722    QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
     1723    if (texture->options & QGLContext::InvertedYBindOption)
     1724        pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
     1725
     1726    // We assume the cost of bound pixmaps is zero
     1727    QGLTextureCache::instance()->insert(q, key, texture, 0);
     1728
     1729    return texture;
     1730#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
     1731}
     1732
     1733
     1734void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
     1735{
     1736#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     1737    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     1738    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     1739    if (pixmapData->gl_surface) {
     1740        glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface);
     1741        pixmapData->gl_surface = 0;
     1742    }
     1743#endif
     1744}
     1745
     1746void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
     1747{
     1748#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
     1749    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     1750    Q_ASSERT(QGLContext::currentContext());
     1751    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     1752    if (pixmapData->gl_surface)
     1753        glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT);
     1754#endif
     1755}
     1756
    14251757QT_END_NAMESPACE
  • trunk/src/opengl/qgl_x11egl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4242#include "qgl.h"
    4343#include <private/qt_x11_p.h>
     44#include <private/qpixmap_x11_p.h>
     45#include <private/qimagepixmapcleanuphooks_p.h>
    4446#include <private/qgl_p.h>
    4547#include <private/qpaintengine_opengl_p.h>
    4648#include "qgl_egl_p.h"
    4749#include "qcolormap.h"
     50#include <QDebug>
    4851
    4952
    5053QT_BEGIN_NAMESPACE
    51 
    52 
    53 bool QGLFormat::hasOpenGL()
    54 {
    55     return true;
    56 }
    5754
    5855bool QGLFormat::hasOpenGLOverlays()
     
    6764}
    6865
     66// Chooses the EGL config and creates the EGL context
    6967bool QGLContext::chooseContext(const QGLContext* shareContext)
    7068{
     
    7775
    7876    // Get the display and initialize it.
    79     d->eglContext = new QEglContext();
    80     d->eglContext->setApi(QEglContext::OpenGL);
    81     if (!d->eglContext->openDisplay(device())) {
    82         delete d->eglContext;
    83         d->eglContext = 0;
    84         return false;
    85     }
    86 
    87     // Construct the configuration we need for this surface.
    88     QEglProperties configProps;
    89     qt_egl_set_format(configProps, devType, d->glFormat);
    90     qt_egl_add_platform_config(configProps, device());
    91     configProps.setRenderableType(QEglContext::OpenGL);
    92 
    93     // Search for a matching configuration, reducing the complexity
    94     // each time until we get something that matches.
    95     if (!d->eglContext->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
    96         delete d->eglContext;
    97         d->eglContext = 0;
    98         return false;
     77    if (d->eglContext == 0) {
     78        d->eglContext = new QEglContext();
     79        d->eglContext->setApi(QEgl::OpenGL);
     80        if (!d->eglContext->openDisplay(device())) {
     81            delete d->eglContext;
     82            d->eglContext = 0;
     83            return false;
     84        }
     85
     86        // Construct the configuration we need for this surface.
     87        QEglProperties configProps;
     88        qt_egl_set_format(configProps, devType, d->glFormat);
     89        qt_egl_add_platform_config(configProps, device());
     90        configProps.setRenderableType(QEgl::OpenGL);
     91
     92#if We_have_an_EGL_library_which_bothers_to_check_EGL_BUFFER_SIZE
     93        if (device()->depth() == 16 && configProps.value(EGL_ALPHA_SIZE) <= 0) {
     94            qDebug("Setting EGL_BUFFER_SIZE to 16");
     95            configProps.setValue(EGL_BUFFER_SIZE, 16);
     96            configProps.setValue(EGL_ALPHA_SIZE, 0);
     97        }
     98
     99        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
     100            delete d->eglContext;
     101            d->eglContext = 0;
     102            return false;
     103        }
     104#else
     105        QEgl::PixelFormatMatch matchType = QEgl::BestPixelFormat;
     106        if ((device()->depth() == 16) && configProps.value(EGL_ALPHA_SIZE) == 0) {
     107            configProps.setValue(EGL_RED_SIZE, 5);
     108            configProps.setValue(EGL_GREEN_SIZE, 6);
     109            configProps.setValue(EGL_BLUE_SIZE, 5);
     110            configProps.setValue(EGL_ALPHA_SIZE, 0);
     111            matchType = QEgl::ExactPixelFormat;
     112        }
     113
     114        // Search for a matching configuration, reducing the complexity
     115        // each time until we get something that matches.
     116        if (!d->eglContext->chooseConfig(configProps, matchType)) {
     117            delete d->eglContext;
     118            d->eglContext = 0;
     119            return false;
     120        }
     121#endif
     122
     123//        qDebug("QGLContext::chooseContext() - using EGL config %d:", d->eglContext->config());
     124//        qDebug() << QEglProperties(d->eglContext->config()).toString();
     125
     126        // Create a new context for the configuration.
     127        if (!d->eglContext->createContext
     128                (shareContext ? shareContext->d_func()->eglContext : 0)) {
     129            delete d->eglContext;
     130            d->eglContext = 0;
     131            return false;
     132        }
     133        d->sharing = d->eglContext->isSharing();
     134        if (d->sharing && shareContext)
     135            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
     136
     137#if defined(EGL_VERSION_1_1)
     138        if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
     139            eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
     140#endif
    99141    }
    100142
     
    102144    qt_egl_update_format(*(d->eglContext), d->glFormat);
    103145
    104     // Create a new context for the configuration.
    105     if (!d->eglContext->createContext
    106             (shareContext ? shareContext->d_func()->eglContext : 0)) {
    107         delete d->eglContext;
    108         d->eglContext = 0;
    109         return false;
    110     }
    111 
    112 #if defined(EGL_VERSION_1_1)
    113     if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
    114         eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
    115 #endif
    116 
    117     // Create the EGL surface to draw into.
    118     if (!d->eglContext->createSurface(device())) {
    119         delete d->eglContext;
    120         d->eglContext = 0;
    121         return false;
    122     }
    123 
    124146    return true;
    125147}
    126 
    127 
    128 void QGLContext::reset()
    129 {
    130     Q_D(QGLContext);
    131     if (!d->valid)
    132         return;
    133     d->cleanup();
    134     doneCurrent();
    135     if (d->eglContext) {
    136         delete d->eglContext;
    137         d->eglContext = 0;
    138     }
    139     d->crWin = false;
    140     d->sharing = false;
    141     d->valid = false;
    142     d->transpColor = QColor();
    143     d->initDone = false;
    144     qgl_share_reg()->removeShare(this);
    145 }
    146 
    147 void QGLContext::makeCurrent()
    148 {
    149     Q_D(QGLContext);
    150     if(!d->valid || !d->eglContext) {
    151         qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
    152         return;
    153     }
    154 
    155     if (d->eglContext->makeCurrent()) {
    156         if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
    157             qgl_context_storage.setLocalData(new QGLThreadContext);
    158         if (qgl_context_storage.hasLocalData())
    159             qgl_context_storage.localData()->context = this;
    160         currentCtx = this;
    161     }
    162 }
    163 
    164 void QGLContext::doneCurrent()
    165 {
    166     Q_D(QGLContext);
    167     if (d->eglContext)
    168         d->eglContext->doneCurrent();
    169 
    170     if (qgl_context_storage.hasLocalData())
    171         qgl_context_storage.localData()->context = 0;
    172     currentCtx = 0;
    173 }
    174 
    175 
    176 void QGLContext::swapBuffers() const
    177 {
    178     Q_D(const QGLContext);
    179     if(!d->valid || !d->eglContext)
    180         return;
    181 
    182     d->eglContext->swapBuffers();
    183 }
    184 
    185 QColor QGLContext::overlayTransparentColor() const
    186 {
    187     return QColor(0, 0, 0);                // Invalid color
    188 }
    189 
    190 uint QGLContext::colorIndex(const QColor &c) const
    191 {
    192     //### color index doesn't work on egl
    193     Q_UNUSED(c);
    194     return 0;
    195 }
    196 
    197 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
    198 {
    199     Q_UNUSED(fnt);
    200     Q_UNUSED(listBase);
    201 }
    202 
    203 void *QGLContext::getProcAddress(const QString &proc) const
    204 {
    205     return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));
    206 }
    207 
    208 void QGLWidget::setMouseTracking(bool enable)
    209 {
    210     QWidget::setMouseTracking(enable);
    211 }
    212 
    213148
    214149void QGLWidget::resizeEvent(QResizeEvent *)
     
    239174}
    240175
     176//#define QT_DEBUG_X11_VISUAL_SELECTION 1
     177
     178bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config, const QX11Info &x11Info, bool useArgbVisual)
     179{
     180    bool foundVisualIsArgb = useArgbVisual;
     181
     182#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     183    qDebug("qt_egl_setup_x11_visual() - useArgbVisual=%d", useArgbVisual);
     184#endif
     185
     186    memset(&vi, 0, sizeof(XVisualInfo));
     187
     188    EGLint eglConfigColorSize;
     189    eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &eglConfigColorSize);
     190
     191    // Check to see if EGL is suggesting an appropriate visual id:
     192    EGLint nativeVisualId;
     193    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId);
     194    vi.visualid = nativeVisualId;
     195
     196    if (vi.visualid) {
     197        // EGL has suggested a visual id, so get the rest of the visual info for that id:
     198        XVisualInfo *chosenVisualInfo;
     199        int matchingCount = 0;
     200        chosenVisualInfo = XGetVisualInfo(x11Info.display(), VisualIDMask, &vi, &matchingCount);
     201        if (chosenVisualInfo) {
     202#if !defined(QT_NO_XRENDER)
     203            if (useArgbVisual) {
     204                // Check to make sure the visual provided by EGL is ARGB
     205                XRenderPictFormat *format;
     206                format = XRenderFindVisualFormat(x11Info.display(), chosenVisualInfo->visual);
     207                if (format->type == PictTypeDirect && format->direct.alphaMask) {
     208#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     209                    qDebug("Using ARGB X Visual ID (%d) provided by EGL", (int)vi.visualid);
     210#endif
     211                    foundVisualIsArgb = true;
     212                    vi = *chosenVisualInfo;
     213                }
     214                else {
     215                    qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this is not ARGB",
     216                             nativeVisualId, (int)config);
     217                    vi.visualid = 0;
     218                }
     219            } else
     220#endif
     221            {
     222                if (eglConfigColorSize == chosenVisualInfo->depth) {
     223#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     224                    qDebug("Using opaque X Visual ID (%d) provided by EGL", (int)vi.visualid);
     225#endif
     226                    vi = *chosenVisualInfo;
     227                } else
     228                    qWarning("Warning: EGL suggested using X visual ID %d (%d bpp) for config %d (%d bpp), but the depths do not match!",
     229                             nativeVisualId, chosenVisualInfo->depth, (int)config, eglConfigColorSize);
     230            }
     231            XFree(chosenVisualInfo);
     232        }
     233        else {
     234            qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
     235                     nativeVisualId, (int)config);
     236            vi.visualid = 0;
     237        }
     238    }
     239
     240    // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
     241    // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
     242         
     243#if !defined(QT_NO_XRENDER)
     244    if (vi.visualid == 0 && useArgbVisual) {
     245        // Try to use XRender to find an ARGB visual we can use
     246        vi.screen  = x11Info.screen();
     247        vi.depth   = 32; //### We might at some point (soon) get ARGB4444
     248        vi.c_class = TrueColor;
     249        XVisualInfo *matchingVisuals;
     250        int matchingCount = 0;
     251        matchingVisuals = XGetVisualInfo(x11Info.display(),
     252                                         VisualScreenMask|VisualDepthMask|VisualClassMask,
     253                                         &vi, &matchingCount);
     254
     255        for (int i = 0; i < matchingCount; ++i) {
     256            XRenderPictFormat *format;
     257            format = XRenderFindVisualFormat(x11Info.display(), matchingVisuals[i].visual);
     258            if (format->type == PictTypeDirect && format->direct.alphaMask) {
     259                vi = matchingVisuals[i];
     260                foundVisualIsArgb = true;
     261#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     262                qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
     263#endif
     264                break;
     265            }
     266        }
     267        XFree(matchingVisuals);
     268    }
     269#endif
     270
     271    if (vi.visualid == 0) {
     272        EGLint depth;
     273        eglGetConfigAttrib(display, config, EGL_BUFFER_SIZE, &depth);
     274        int err;
     275        err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
     276        if (err == 0) {
     277            qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!",
     278                     (int)config, depth);
     279            depth = x11Info.depth();
     280            err = XMatchVisualInfo(x11Info.display(), x11Info.screen(), depth, TrueColor, &vi);
     281            if (err == 0) {
     282                qWarning("Error: Couldn't get any matching X visual!");
     283                return false;
     284            } else
     285                qWarning("         - Falling back to X11 suggested depth (%d)", depth);
     286        }
     287#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     288        else
     289            qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
     290#endif
     291
     292        // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
     293        if (useArgbVisual)
     294            foundVisualIsArgb = vi.depth == 32; //### We might at some point (soon) get ARGB4444
     295    }
     296
     297#ifdef QT_DEBUG_X11_VISUAL_SELECTION
     298    qDebug("Visual Info:");
     299    qDebug("   bits_per_rgb=%d", vi.bits_per_rgb);
     300    qDebug("   red_mask=0x%x", vi.red_mask);
     301    qDebug("   green_mask=0x%x", vi.green_mask);
     302    qDebug("   blue_mask=0x%x", vi.blue_mask);
     303    qDebug("   colormap_size=%d", vi.colormap_size);
     304    qDebug("   c_class=%d", vi.c_class);
     305    qDebug("   depth=%d", vi.depth);
     306    qDebug("   screen=%d", vi.screen);
     307    qDebug("   visualid=%d", vi.visualid);
     308#endif
     309    return foundVisualIsArgb;
     310}
     311
    241312void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
    242313{
     
    263334    }
    264335
    265     bool visible = isVisible();
    266     if (visible)
    267         hide();
    268 
    269     XVisualInfo vi;
    270 
    271     int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi);
    272     if (err == 0) {
    273         qWarning("Error: Couldn't get a matching X visual for format");
    274         return;
    275     }
    276 
    277     XSetWindowAttributes a;
    278 
    279     Window p = RootWindow(X11->display, vi.screen);
    280     if (parentWidget())
    281         p = parentWidget()->winId();
    282 
    283     QColormap colmap = QColormap::instance(vi.screen);
    284     a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
    285     a.border_pixel = colmap.pixel(Qt::black);
    286 
    287     Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
    288                               0, vi.depth, InputOutput, vi.visual,
    289                               CWBackPixel|CWBorderPixel, &a);
    290 
    291     if (deleteOldContext)
    292         delete oldcx;
    293     oldcx = 0;
    294 
    295     create(w); // Create with the ID of the window we've just created
    296 
    297     d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
    298 
    299     if (visible)
    300         show();
     336    // If the application has set WA_TranslucentBackground and not explicitly set
     337    // the alpha buffer size to zero, modify the format so it have an alpha channel
     338    QGLFormat& fmt = d->glcx->d_func()->glFormat;
     339    const bool tryArgbVisual = testAttribute(Qt::WA_TranslucentBackground) || fmt.alpha();
     340    if (tryArgbVisual && fmt.alphaBufferSize() == -1)
     341        fmt.setAlphaBufferSize(1);
    301342
    302343    bool createFailed = false;
    303344    if (!d->glcx->isValid()) {
     345        // Create the QGLContext here, which in turn chooses the EGL config
     346        // and creates the EGL context:
    304347        if (!d->glcx->create(shareContext ? shareContext : oldcx))
    305348            createFailed = true;
     
    317360    }
    318361
     362    bool visible = isVisible();
     363    if (visible)
     364        hide();
     365
     366    XVisualInfo vi;
     367    QEglContext *eglContext = d->glcx->d_func()->eglContext;
     368    bool usingArgbVisual = qt_egl_setup_x11_visual(vi, eglContext->display(), eglContext->config(),
     369                                                   x11Info(), tryArgbVisual);
     370
     371    XSetWindowAttributes a;
     372
     373    Window p = RootWindow(x11Info().display(), x11Info().screen());
     374    if (parentWidget())
     375        p = parentWidget()->winId();
     376
     377    QColormap colmap = QColormap::instance(vi.screen);
     378    a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
     379    a.border_pixel = colmap.pixel(Qt::black);
     380
     381    unsigned int valueMask = CWBackPixel|CWBorderPixel;
     382    if (usingArgbVisual) {
     383        a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone);
     384        valueMask |= CWColormap;
     385    }
     386
     387    Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(),
     388                             0, vi.depth, InputOutput, vi.visual, valueMask, &a);
     389
     390    if (deleteOldContext)
     391        delete oldcx;
     392    oldcx = 0;
     393
     394    create(w); // Create with the ID of the window we've just created
     395
     396
     397    // Create the EGL surface to draw into.
     398    QGLContextPrivate *ctxpriv = d->glcx->d_func();
     399    ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(this);
     400    if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
     401        delete ctxpriv->eglContext;
     402        ctxpriv->eglContext = 0;
     403        return;
     404    }
     405
     406    d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
     407
     408    if (visible)
     409        show();
     410
     411    XFlush(X11->display);
    319412    d->glcx->setWindowCreated(true);
    320413}
     
    332425}
    333426
    334 bool QGLWidgetPrivate::renderCxPm(QPixmap*)
    335 {
    336     return false;
    337 }
    338 
    339427void QGLWidgetPrivate::cleanupColormaps()
    340428{
     
    357445        return;
    358446    init_done = true;
     447
     448    // We need a context current to initialize the extensions.
     449    QGLWidget tmpWidget;
     450    tmpWidget.makeCurrent();
     451
    359452    init_extensions();
     453
     454    tmpWidget.doneCurrent();
    360455}
    361456
     
    369464    if ( force || (currentId != eglSurfaceWindowId) ) {
    370465        // The window id has changed so we need to re-create the EGL surface
    371         if (!glcx->d_func()->eglContext->recreateSurface(q))
     466        QEglContext *ctx = glcx->d_func()->eglContext;
     467        EGLSurface surface = glcx->d_func()->eglSurface;
     468        if (surface != EGL_NO_SURFACE)
     469            ctx->destroySurface(surface); // Will force doneCurrent() if nec.
     470        surface = ctx->createSurface(q);
     471        if (surface == EGL_NO_SURFACE)
    372472            qWarning("Error creating EGL window surface: 0x%x", eglGetError());
     473        glcx->d_func()->eglSurface = surface;
    373474
    374475        eglSurfaceWindowId = currentId;
     
    376477}
    377478
     479// Selects which configs should be used
     480EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly)
     481{
     482    // Cache the configs we select as they wont change:
     483    static EGLConfig roPixmapRGBConfig = 0;
     484    static EGLConfig roPixmapRGBAConfig = 0;
     485    static EGLConfig rwPixmapRGBConfig = 0;
     486    static EGLConfig rwPixmapRGBAConfig = 0;
     487
     488    EGLConfig* targetConfig;
     489
     490    if (hasAlpha) {
     491        if (readOnly)
     492            targetConfig = &roPixmapRGBAConfig;
     493        else
     494            targetConfig = &rwPixmapRGBAConfig;
     495    }
     496    else {
     497        if (readOnly)
     498            targetConfig = &roPixmapRGBConfig;
     499        else
     500            targetConfig = &rwPixmapRGBConfig;
     501    }
     502
     503    if (*targetConfig == 0) {
     504        QEglProperties configAttribs;
     505        configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
     506        configAttribs.setRenderableType(QEgl::OpenGL);
     507        if (hasAlpha)
     508            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
     509        else
     510            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
     511
     512        // If this is going to be a render target, it needs to have a depth, stencil & sample buffer
     513        if (!readOnly) {
     514            configAttribs.setValue(EGL_DEPTH_SIZE, 1);
     515            configAttribs.setValue(EGL_STENCIL_SIZE, 1);
     516            configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
     517        }
     518
     519        EGLint configCount = 0;
     520        do {
     521            eglChooseConfig(QEglContext::defaultDisplay(0), configAttribs.properties(), targetConfig, 1, &configCount);
     522            if (configCount > 0) {
     523                // Got one
     524                qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" )
     525                         << "config (" << int(*targetConfig) << ") to create a pixmap surface:";
     526
     527//                QEglProperties configProps(*targetConfig);
     528//                qDebug() << configProps.toString();
     529                break;
     530            }
     531            qWarning("choosePixmapConfig() - No suitible config found, reducing requirements");
     532        } while (configAttribs.reduceConfiguration());
     533    }
     534
     535    if (*targetConfig == 0)
     536        qWarning("choosePixmapConfig() - Couldn't find a suitable config");
     537
     538    return *targetConfig;
     539}
     540
     541bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly)
     542{
     543    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     544    QX11PixmapData* pixmapData = static_cast<QX11PixmapData*>(pmd);
     545
     546    bool hasAlpha = pixmapData->hasAlphaChannel();
     547
     548    EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly);
     549
     550    QEglProperties pixmapAttribs;
     551
     552    // If the pixmap can't be bound to a texture, it's pretty useless
     553    pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
     554    if (hasAlpha)
     555        pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
     556    else
     557        pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
     558
     559    EGLSurface pixmapSurface;
     560    pixmapSurface = eglCreatePixmapSurface(QEglContext::defaultDisplay(0),
     561                                           pixmapConfig,
     562                                           (EGLNativePixmapType) pixmapData->handle(),
     563                                           pixmapAttribs.properties());
     564//    qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x",
     565//           pixmapSurface, pixmapData->handle());
     566    if (pixmapSurface == EGL_NO_SURFACE) {
     567        qWarning() << "Failed to create a pixmap surface using config" << (int)pixmapConfig
     568                   << ":" << QEglContext::errorString(eglGetError());
     569        return false;
     570    }
     571
     572    static bool doneOnce = false;
     573    if (!doneOnce) {
     574        // Make sure QGLTextureCache is instanciated so it can install cleanup hooks
     575        // which cleanup the EGL surface.
     576        QGLTextureCache::instance();
     577        doneOnce = true;
     578    }
     579
     580    Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
     581    pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
     582    QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called
     583
     584    return true;
     585}
     586
     587
     588QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key,
     589                                                           QGLContext::BindOptions options)
     590{
     591    Q_Q(QGLContext);
     592
     593    // The EGL texture_from_pixmap has no facility to invert the y coordinate
     594    if (!(options & QGLContext::CanFlipNativePixmapBindOption))
     595        return 0;
     596
     597    Q_ASSERT(pd->classId() == QPixmapData::X11Class);
     598
     599    static bool checkedForTFP = false;
     600    static bool haveTFP = false;
     601
     602    if (!checkedForTFP) {
     603        // Check for texture_from_pixmap egl extension
     604        checkedForTFP = true;
     605        if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
     606            eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
     607        {
     608            qDebug("Found texture_from_pixmap EGL extension!");
     609            haveTFP = true;
     610        }
     611    }
     612
     613    if (!haveTFP)
     614        return 0;
     615
     616    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
     617
     618    bool hasAlpha = pixmapData->hasAlphaChannel();
     619
     620    // Check to see if the surface is still valid
     621    if (pixmapData->gl_surface &&
     622        hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
     623    {
     624        // Surface is invalid!
     625        destroyGlSurfaceForPixmap(pixmapData);
     626    }
     627
     628    if (pixmapData->gl_surface == 0) {
     629        bool success = qt_createEGLSurfaceForPixmap(pixmapData, true);
     630        if (!success) {
     631            haveTFP = false;
     632            return 0;
     633        }
     634    }
     635
     636    Q_ASSERT(pixmapData->gl_surface);
     637
     638    GLuint textureId;
     639    glGenTextures(1, &textureId);
     640    glBindTexture(GL_TEXTURE_2D, textureId);
     641
     642    // bind the egl pixmap surface to a texture
     643    EGLBoolean success;
     644    success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
     645    if (success == EGL_FALSE) {
     646        qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
     647        eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface);
     648        pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
     649        haveTFP = false;
     650        return 0;
     651    }
     652
     653    QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
     654    pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
     655
     656    // We assume the cost of bound pixmaps is zero
     657    QGLTextureCache::instance()->insert(q, key, texture, 0);
     658
     659    glBindTexture(GL_TEXTURE_2D, textureId);
     660    return texture;
     661}
     662
     663void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
     664{
     665    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     666    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     667    if (pixmapData->gl_surface) {
     668        EGLBoolean success;
     669        success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
     670        if (success == EGL_FALSE) {
     671            qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
     672                       << QEglContext::errorString(eglGetError());
     673        }
     674        pixmapData->gl_surface = 0;
     675    }
     676}
     677
     678void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
     679{
     680    Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
     681    QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
     682    if (pixmapData->gl_surface) {
     683        EGLBoolean success;
     684        success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
     685                                     (EGLSurface)pixmapData->gl_surface,
     686                                     EGL_BACK_BUFFER);
     687        if (success == EGL_FALSE) {
     688            qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
     689                       << QEglContext::errorString(eglGetError());
     690        }
     691    }
     692}
     693
    378694QT_END_NAMESPACE
  • trunk/src/opengl/qglcolormap.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4343    \class QGLColormap
    4444    \brief The QGLColormap class is used for installing custom colormaps into
    45     QGLWidgets.
     45    a QGLWidget.
    4646
    4747    \module OpenGL
    48     \ingroup multimedia
     48    \ingroup painting-3D
    4949    \ingroup shared
    5050
    5151    QGLColormap provides a platform independent way of specifying and
    52     installing indexed colormaps into QGLWidgets. QGLColormap is
     52    installing indexed colormaps for a QGLWidget. QGLColormap is
    5353    especially useful when using the OpenGL color-index mode.
    5454
     
    6262    colormap flashing if your X server is running in 8 bit mode.
    6363
    64     Under Windows the size of the colormap is always set to 256
     64    The size() of the colormap is always set to 256
    6565    colors. Note that under Windows you can also install colormaps
    6666    in child widgets.
     
    175175    if (!d->cells)
    176176        d->cells = new QVector<QRgb>(256);
    177     d->cells->insert(idx, color);
     177    d->cells->replace(idx, color);
    178178}
    179179
     
    181181    Set an array of cells in this colormap. \a count is the number of
    182182    colors that should be set, \a colors is the array of colors, and
    183     \a base is the starting index.
     183    \a base is the starting index.  The first element in \a colors
     184    is set at \a base in the colormap.
    184185*/
    185186void QGLColormap::setEntries(int count, const QRgb *colors, int base)
     
    189190        d->cells = new QVector<QRgb>(256);
    190191
    191     Q_ASSERT_X(!colors || base >= 0 || base + count < d->cells->size(), "QGLColormap::setEntries",
     192    Q_ASSERT_X(colors && base >= 0 && (base + count) <= d->cells->size(), "QGLColormap::setEntries",
    192193               "preconditions not met");
    193     for (int i = base; i < base + count; ++i)
    194         setEntry(i, colors[i]);
     194    for (int i = 0; i < count; ++i)
     195        setEntry(base + i, colors[i]);
    195196}
    196197
     
    228229
    229230/*!
    230     Returns true if the colormap is empty; otherwise returns false. A
    231     colormap with no color values set is considered to be empty.
     231    Returns true if the colormap is empty or it is not in use
     232    by a QGLWidget; otherwise returns false.
     233
     234    A colormap with no color values set is considered to be empty.
     235    For historical reasons, a colormap that has color values set
     236    but which is not in use by a QGLWidget is also considered empty.
     237
     238    Compare size() with zero to determine if the colormap is empty
     239    regardless of whether it is in use by a QGLWidget or not.
     240
     241    \sa size()
    232242*/
    233243bool QGLColormap::isEmpty() const
  • trunk/src/opengl/qglcolormap.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/opengl/qglextensions.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4444QT_BEGIN_NAMESPACE
    4545
     46static void *qt_gl_getProcAddress_search
     47    (QGLContext *ctx, const char *name1, const char *name2,
     48     const char *name3, const char *name4)
     49{
     50    void *addr;
     51
     52    addr = ctx->getProcAddress(QLatin1String(name1));
     53    if (addr)
     54        return addr;
     55
     56    addr = ctx->getProcAddress(QLatin1String(name2));
     57    if (addr)
     58        return addr;
     59
     60    addr = ctx->getProcAddress(QLatin1String(name3));
     61    if (addr)
     62        return addr;
     63
     64    if (name4)
     65        return ctx->getProcAddress(QLatin1String(name4));
     66
     67    return 0;
     68}
     69
     70// Search for an extension function starting with the most likely
     71// function suffix first, and then trying the other variations.
     72#if defined(QT_OPENGL_ES)
     73#define qt_gl_getProcAddress(ctx,name) \
     74    qt_gl_getProcAddress_search((ctx), name, name "OES", name "EXT", name "ARB")
     75#define qt_gl_getProcAddressEXT(ctx,name) \
     76    qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
     77#define qt_gl_getProcAddressARB(ctx,name) \
     78    qt_gl_getProcAddress_search((ctx), name "OES", name, name "ARB", name "EXT")
     79#define qt_gl_getProcAddressOES(ctx,name) \
     80    qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
     81#else
     82#define qt_gl_getProcAddress(ctx,name) \
     83    qt_gl_getProcAddress_search((ctx), name, name "ARB", name "EXT", 0)
     84#define qt_gl_getProcAddressEXT(ctx,name) \
     85    qt_gl_getProcAddress_search((ctx), name "EXT", name, name "ARB", 0)
     86#define qt_gl_getProcAddressARB(ctx,name) \
     87    qt_gl_getProcAddress_search((ctx), name "ARB", name, name "EXT", 0)
     88#define qt_gl_getProcAddressOES(ctx,name) \
     89    qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
     90#endif
     91
    4692bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
    4793{
    48 #if !defined(QT_OPENGL_ES_2)
    49     if (glIsRenderbufferEXT != 0)
    50         return true;
     94#if defined(QT_OPENGL_ES_2)
     95    static bool have_resolved = false;
     96    if (have_resolved)
     97        return true;
     98    have_resolved = true;
     99#else
     100    if (glIsRenderbuffer != 0)
     101        return true;
     102#endif
    51103
    52104    if (ctx == 0) {
     
    56108    }
    57109
    58     glIsRenderbufferEXT = (_glIsRenderbufferEXT) ctx->getProcAddress(QLatin1String("glIsRenderbufferEXT"));
    59     glBindRenderbufferEXT = (_glBindRenderbufferEXT) ctx->getProcAddress(QLatin1String("glBindRenderbufferEXT"));
    60     glDeleteRenderbuffersEXT = (_glDeleteRenderbuffersEXT) ctx->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT"));
    61     glGenRenderbuffersEXT = (_glGenRenderbuffersEXT) ctx->getProcAddress(QLatin1String("glGenRenderbuffersEXT"));
    62     glRenderbufferStorageEXT = (_glRenderbufferStorageEXT) ctx->getProcAddress(QLatin1String("glRenderbufferStorageEXT"));
    63     glGetRenderbufferParameterivEXT =
    64         (_glGetRenderbufferParameterivEXT) ctx->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT"));
    65     glIsFramebufferEXT = (_glIsFramebufferEXT) ctx->getProcAddress(QLatin1String("glIsFramebufferEXT"));
    66     glBindFramebufferEXT = (_glBindFramebufferEXT) ctx->getProcAddress(QLatin1String("glBindFramebufferEXT"));
    67     glDeleteFramebuffersEXT = (_glDeleteFramebuffersEXT) ctx->getProcAddress(QLatin1String("glDeleteFramebuffersEXT"));
    68     glGenFramebuffersEXT = (_glGenFramebuffersEXT) ctx->getProcAddress(QLatin1String("glGenFramebuffersEXT"));
    69     glCheckFramebufferStatusEXT = (_glCheckFramebufferStatusEXT) ctx->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT"));
    70     glFramebufferTexture1DEXT = (_glFramebufferTexture1DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture1DEXT"));
    71     glFramebufferTexture2DEXT = (_glFramebufferTexture2DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture2DEXT"));
    72     glFramebufferTexture3DEXT = (_glFramebufferTexture3DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture3DEXT"));
    73     glFramebufferRenderbufferEXT = (_glFramebufferRenderbufferEXT) ctx->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT"));
    74     glGetFramebufferAttachmentParameterivEXT =
    75         (_glGetFramebufferAttachmentParameterivEXT) ctx->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT"));
    76     glGenerateMipmapEXT = (_glGenerateMipmapEXT) ctx->getProcAddress(QLatin1String("glGenerateMipmapEXT"));
    77     return glIsRenderbufferEXT;
     110
     111    glBlitFramebufferEXT = (_glBlitFramebufferEXT) qt_gl_getProcAddressEXT(ctx, "glBlitFramebuffer");
     112    glRenderbufferStorageMultisampleEXT =
     113        (_glRenderbufferStorageMultisampleEXT) qt_gl_getProcAddressEXT(ctx, "glRenderbufferStorageMultisample");
     114
     115#if !defined(QT_OPENGL_ES_2)
     116    glIsRenderbuffer = (_glIsRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glIsRenderbuffer");
     117    if (!glIsRenderbuffer)
     118        return false;   // Not much point searching for anything else.
     119    glBindRenderbuffer = (_glBindRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glBindRenderbuffer");
     120    glDeleteRenderbuffers = (_glDeleteRenderbuffers) qt_gl_getProcAddressEXT(ctx, "glDeleteRenderbuffers");
     121    glGenRenderbuffers = (_glGenRenderbuffers) qt_gl_getProcAddressEXT(ctx, "glGenRenderbuffers");
     122    glRenderbufferStorage = (_glRenderbufferStorage) qt_gl_getProcAddressEXT(ctx, "glRenderbufferStorage");
     123    glGetRenderbufferParameteriv =
     124        (_glGetRenderbufferParameteriv) qt_gl_getProcAddressEXT(ctx, "glGetRenderbufferParameteriv");
     125    glIsFramebuffer = (_glIsFramebuffer) qt_gl_getProcAddressEXT(ctx, "glIsFramebuffer");
     126    glBindFramebuffer = (_glBindFramebuffer) qt_gl_getProcAddressEXT(ctx, "glBindFramebuffer");
     127    glDeleteFramebuffers = (_glDeleteFramebuffers) qt_gl_getProcAddressEXT(ctx, "glDeleteFramebuffers");
     128    glGenFramebuffers = (_glGenFramebuffers) qt_gl_getProcAddressEXT(ctx, "glGenFramebuffers");
     129    glCheckFramebufferStatus = (_glCheckFramebufferStatus) qt_gl_getProcAddressEXT(ctx, "glCheckFramebufferStatus");
     130    glFramebufferTexture2D = (_glFramebufferTexture2D) qt_gl_getProcAddressEXT(ctx, "glFramebufferTexture2D");
     131    glFramebufferRenderbuffer = (_glFramebufferRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glFramebufferRenderbuffer");
     132    glGetFramebufferAttachmentParameteriv =
     133        (_glGetFramebufferAttachmentParameteriv) qt_gl_getProcAddressEXT(ctx, "glGetFramebufferAttachmentParameteriv");
     134    glGenerateMipmap = (_glGenerateMipmap) qt_gl_getProcAddressEXT(ctx, "glGenerateMipmap");
     135
     136    return glIsRenderbuffer != 0;
    78137#else
    79     Q_UNUSED(ctx);
    80138    return true;
    81139#endif
    82140}
    83141
     142#if !defined(QT_OPENGL_ES_2)
    84143bool qt_resolve_version_1_3_functions(QGLContext *ctx)
    85144{
     
    90149    glMultiTexCoord4f = (_glMultiTexCoord4f) ctx->getProcAddress(QLatin1String("glMultiTexCoord4f"));
    91150
    92 #if defined(QT_OPENGL_ES_2)
    93     return glMultiTexCoord4f;
    94 #else
    95151    glActiveTexture = (_glActiveTexture) ctx->getProcAddress(QLatin1String("glActiveTexture"));
    96152    return glMultiTexCoord4f && glActiveTexture;
    97 #endif
    98 }
    99 
     153}
     154#endif
     155
     156#if !defined(QT_OPENGL_ES_2)
    100157bool qt_resolve_stencil_face_extension(QGLContext *ctx)
    101158{
     
    108165    return glActiveStencilFaceEXT;
    109166}
    110 
     167#endif
     168
     169
     170#if !defined(QT_OPENGL_ES_2)
    111171bool qt_resolve_frag_program_extensions(QGLContext *ctx)
    112172{
     
    127187        && glProgramLocalParameter4fvARB;
    128188}
     189#endif
     190
    129191
    130192bool qt_resolve_buffer_extensions(QGLContext *ctx)
    131193{
    132     if (glBindBufferARB && glDeleteBuffersARB && glGenBuffersARB && glBufferDataARB
    133         && glMapBufferARB && glUnmapBufferARB)
    134         return true;
    135 
    136     glBindBufferARB = (_glBindBufferARB) ctx->getProcAddress(QLatin1String("glBindBufferARB"));
    137     glDeleteBuffersARB = (_glDeleteBuffersARB) ctx->getProcAddress(QLatin1String("glDeleteBuffersARB"));
    138     glGenBuffersARB = (_glGenBuffersARB) ctx->getProcAddress(QLatin1String("glGenBuffersARB"));
    139     glBufferDataARB = (_glBufferDataARB) ctx->getProcAddress(QLatin1String("glBufferDataARB"));
    140     glMapBufferARB = (_glMapBufferARB) ctx->getProcAddress(QLatin1String("glMapBufferARB"));
    141     glUnmapBufferARB = (_glUnmapBufferARB) ctx->getProcAddress(QLatin1String("glUnmapBufferARB"));
    142 
    143     return glBindBufferARB
    144         && glDeleteBuffersARB
    145         && glGenBuffersARB
    146         && glBufferDataARB
    147         && glMapBufferARB
    148         && glUnmapBufferARB;
     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)
     202    glBindBuffer = (_glBindBuffer) qt_gl_getProcAddressARB(ctx, "glBindBuffer");
     203    glDeleteBuffers = (_glDeleteBuffers) qt_gl_getProcAddressARB(ctx, "glDeleteBuffers");
     204    glGenBuffers = (_glGenBuffers) qt_gl_getProcAddressARB(ctx, "glGenBuffers");
     205    glBufferData = (_glBufferData) qt_gl_getProcAddressARB(ctx, "glBufferData");
     206#endif
     207    glMapBufferARB = (_glMapBufferARB) qt_gl_getProcAddressARB(ctx, "glMapBuffer");
     208    glUnmapBufferARB = (_glUnmapBufferARB) qt_gl_getProcAddressARB(ctx, "glUnmapBuffer");
     209
     210    return glMapBufferARB
     211        && glUnmapBufferARB
     212#if !defined(QT_OPENGL_ES_2)
     213        && glBindBuffer
     214        && glDeleteBuffers
     215        && glGenBuffers
     216        && glBufferData
     217#endif
     218        ;
    149219}
    150220
    151221bool qt_resolve_glsl_extensions(QGLContext *ctx)
    152222{
     223#if defined(QT_OPENGL_ES_2)
     224    // The GLSL shader functions are always present in OpenGL/ES 2.0.
     225    // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
     226    if (!QGLContextPrivate::extensionFuncs(ctx).qt_glslResolved) {
     227        glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
     228        glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
     229        QGLContextPrivate::extensionFuncs(ctx).qt_glslResolved = true;
     230    }
     231    return true;
     232#else
    153233    if (glCreateShader)
    154234        return true;
    155235
    156236    glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
    157     glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
    158     glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
    159     glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
    160 
    161     glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
    162     glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
    163     glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
    164     glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
    165     glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
    166     glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
    167 
    168     glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
    169     glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
    170     glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
    171 
    172     glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
    173     glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
    174     glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
    175     glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
    176     glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
    177     glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
    178 
    179     return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
    180         glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
    181         glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
    182         glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
    183 }
     237    if (glCreateShader) {
     238        glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
     239        glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
     240        glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
     241        glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
     242        glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
     243
     244        glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
     245        glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
     246        glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
     247        glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
     248        glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
     249        glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
     250        glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
     251
     252        glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
     253        glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
     254        glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
     255        glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
     256        glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
     257
     258        glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
     259        glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
     260        glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
     261        glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
     262        glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
     263        glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
     264        glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
     265        glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
     266        glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
     267        glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
     268        glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
     269        glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
     270        glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
     271        glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
     272        glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
     273        glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
     274
     275        glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
     276        glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
     277        glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
     278        glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
     279        glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
     280        glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
     281        glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
     282        glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
     283        glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
     284
     285    } else {
     286        // We may not have the standard shader functions, but we might
     287        // have the older ARB functions instead.
     288        glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
     289        glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
     290        glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
     291        glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
     292        glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
     293        glIsShader = 0;
     294
     295        glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
     296        glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
     297        glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
     298        glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
     299        glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
     300        glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
     301        glIsProgram = 0;
     302
     303        glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
     304        glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
     305        glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
     306        glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
     307        glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
     308
     309        glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
     310        glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
     311        glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
     312        glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
     313        glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
     314        glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
     315        glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
     316        glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
     317        glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
     318        glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
     319        glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
     320        glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
     321        glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
     322        glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
     323        glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
     324        glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
     325
     326        glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
     327        glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
     328        glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
     329        glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
     330        glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
     331        glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
     332        glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
     333        glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
     334        glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
     335    }
     336
     337    // Note: glShaderBinary(), glIsShader(), glIsProgram(), and
     338    // glUniformMatrixNxMfv() are optional, but all other functions
     339    // are required.
     340
     341    return glCreateShader &&
     342        glShaderSource &&
     343        glCompileShader &&
     344        glDeleteProgram &&
     345        glCreateProgram &&
     346        glAttachShader &&
     347        glDetachShader &&
     348        glLinkProgram &&
     349        glUseProgram &&
     350        glDeleteProgram &&
     351        glGetShaderInfoLog &&
     352        glGetShaderiv &&
     353        glGetShaderSource &&
     354        glGetProgramiv &&
     355        glGetProgramInfoLog &&
     356        glGetUniformLocation &&
     357        glUniform1fv &&
     358        glUniform2fv &&
     359        glUniform3fv &&
     360        glUniform4fv &&
     361        glUniform1i &&
     362        glUniform1iv &&
     363        glUniformMatrix2fv &&
     364        glUniformMatrix3fv &&
     365        glUniformMatrix4fv &&
     366        glBindAttribLocation &&
     367        glGetAttribLocation &&
     368        glVertexAttrib1fv &&
     369        glVertexAttrib2fv &&
     370        glVertexAttrib3fv &&
     371        glVertexAttrib4fv &&
     372        glVertexAttribPointer &&
     373        glDisableVertexAttribArray &&
     374        glEnableVertexAttribArray;
     375#endif
     376}
     377
     378#if !defined(QT_OPENGL_ES_2)
     379bool qt_resolve_version_2_0_functions(QGLContext *ctx)
     380{
     381    bool gl2supported = true;
     382    if (!qt_resolve_glsl_extensions(ctx))
     383        gl2supported = false;
     384
     385    if (!qt_resolve_version_1_3_functions(ctx))
     386        gl2supported = false;
     387
     388    if (!qt_resolve_framebufferobject_extensions(ctx))
     389        gl2supported = false;
     390
     391    if (glStencilOpSeparate)
     392        return gl2supported;
     393
     394    glBlendColor = (_glBlendColor) ctx->getProcAddress(QLatin1String("glBlendColor"));
     395    glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate"));
     396    if (!glBlendColor || !glStencilOpSeparate)
     397        gl2supported = false;
     398
     399    return gl2supported;
     400}
     401#endif
     402
    184403
    185404QT_END_NAMESPACE
  • trunk/src/opengl/qglextensions_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    7575#endif
    7676
     77#ifndef GL_VERSION_2_0
     78typedef char GLchar;
     79#endif
     80
    7781// ARB_pixel_buffer_object
    78 typedef void (APIENTRY *_glBindBufferARB) (GLenum, GLuint);
    79 typedef void (APIENTRY *_glDeleteBuffersARB) (GLsizei, const GLuint *);
    80 typedef void (APIENTRY *_glGenBuffersARB) (GLsizei, GLuint *);
    81 typedef void (APIENTRY *_glBufferDataARB) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
     82typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint);
     83typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *);
     84typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *);
     85typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
    8286typedef GLvoid* (APIENTRY *_glMapBufferARB) (GLenum, GLenum);
    8387typedef GLboolean (APIENTRY *_glUnmapBufferARB) (GLenum);
     
    9397typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
    9498typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
     99typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
    95100typedef void (APIENTRY *_glCompileShader) (GLuint);
    96101typedef void (APIENTRY *_glDeleteShader) (GLuint);
     102typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
    97103
    98104typedef GLuint (APIENTRY *_glCreateProgram) ();
     
    102108typedef void (APIENTRY *_glUseProgram) (GLuint);
    103109typedef void (APIENTRY *_glDeleteProgram) (GLuint);
     110typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
    104111
    105112typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
    106113typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
     114typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
    107115typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
     116typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
    108117
    109118typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
    110 typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
    111 typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
    112 typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
    113 typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
     119typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
     120typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
     121typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
     122typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
    114123typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
    115 
     124typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
     125typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     126typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     127typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     128typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     129typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     130typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     131typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     132typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     133typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
     134
     135typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
     136typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
     137typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
     138typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
     139typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
     140typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
     141typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
     142typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
     143typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
     144
     145typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
     146typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
     147
     148
     149typedef void (APIENTRY *_glMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
    116150typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
    117151
    118 typedef void (APIENTRY *_glMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
     152// Needed for GL2 engine:
     153typedef void (APIENTRY *_glStencilOpSeparate) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
    119154typedef void (APIENTRY *_glActiveTexture) (GLenum);
     155typedef void (APIENTRY *_glBlendColor) (GLclampf, GLclampf, GLclampf, GLclampf);
     156
    120157
    121158// EXT_GL_framebuffer_object
    122 typedef GLboolean (APIENTRY *_glIsRenderbufferEXT) (GLuint renderbuffer);
    123 typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum target, GLuint renderbuffer);
    124 typedef void (APIENTRY *_glDeleteRenderbuffersEXT) (GLsizei n, const GLuint *renderbuffers);
    125 typedef void (APIENTRY *_glGenRenderbuffersEXT) (GLsizei n, GLuint *renderbuffers);
    126 typedef void (APIENTRY *_glRenderbufferStorageEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
    127 typedef void (APIENTRY *_glGetRenderbufferParameterivEXT) (GLenum target, GLenum pname, GLint *params);
    128 typedef GLboolean (APIENTRY *_glIsFramebufferEXT) (GLuint framebuffer);
    129 typedef void (APIENTRY *_glBindFramebufferEXT) (GLenum target, GLuint framebuffer);
    130 typedef void (APIENTRY *_glDeleteFramebuffersEXT) (GLsizei n, const GLuint *framebuffers);
    131 typedef void (APIENTRY *_glGenFramebuffersEXT) (GLsizei n, GLuint *framebuffers);
    132 typedef GLenum (APIENTRY *_glCheckFramebufferStatusEXT) (GLenum target);
    133 typedef void (APIENTRY *_glFramebufferTexture1DEXT) (GLenum target, GLenum attachment, GLenum textarget,
     159typedef GLboolean (APIENTRY *_glIsRenderbuffer) (GLuint renderbuffer);
     160typedef void (APIENTRY *_glBindRenderbuffer) (GLenum target, GLuint renderbuffer);
     161typedef void (APIENTRY *_glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers);
     162typedef void (APIENTRY *_glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers);
     163typedef void (APIENTRY *_glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
     164typedef void (APIENTRY *_glGetRenderbufferParameteriv) (GLenum target, GLenum pname, GLint *params);
     165typedef GLboolean (APIENTRY *_glIsFramebuffer) (GLuint framebuffer);
     166typedef void (APIENTRY *_glBindFramebuffer) (GLenum target, GLuint framebuffer);
     167typedef void (APIENTRY *_glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers);
     168typedef void (APIENTRY *_glGenFramebuffers) (GLsizei n, GLuint *framebuffers);
     169typedef GLenum (APIENTRY *_glCheckFramebufferStatus) (GLenum target);
     170typedef void (APIENTRY *_glFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget,
    134171                                                           GLuint texture, GLint level);
    135 typedef void (APIENTRY *_glFramebufferTexture2DEXT) (GLenum target, GLenum attachment, GLenum textarget,
    136                                                            GLuint texture, GLint level);
    137 typedef void (APIENTRY *_glFramebufferTexture3DEXT) (GLenum target, GLenum attachment, GLenum textarget,
    138                                                            GLuint texture, GLint level, GLint zoffset);
    139 typedef void (APIENTRY *_glFramebufferRenderbufferEXT) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
     172typedef void (APIENTRY *_glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
    140173                                                              GLuint renderbuffer);
    141 typedef void (APIENTRY *_glGetFramebufferAttachmentParameterivEXT) (GLenum target, GLenum attachment, GLenum pname,
     174typedef void (APIENTRY *_glGetFramebufferAttachmentParameteriv) (GLenum target, GLenum attachment, GLenum pname,
    142175                                                                          GLint *params);
    143 typedef void (APIENTRY *_glGenerateMipmapEXT) (GLenum target);
     176typedef void (APIENTRY *_glGenerateMipmap) (GLenum target);
     177
     178// EXT_GL_framebuffer_blit
     179typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1, int srcY1,
     180                                                int dstX0, int dstY0, int dstX1, int dstY1,
     181                                                GLbitfield mask, GLenum filter);
     182
     183// EXT_GL_framebuffer_multisample
     184typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
     185                                                               GLenum internalformat, GLsizei width, GLsizei height);
     186
     187// ARB_texture_compression
     188typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
     189                                                     GLsizei, GLint, GLsizei, const GLvoid *);
    144190
    145191QT_BEGIN_NAMESPACE
     
    148194{
    149195    QGLExtensionFuncs() {
     196#if !defined(QT_OPENGL_ES_2)
    150197        qt_glProgramStringARB = 0;
    151198        qt_glBindProgramARB = 0;
     
    154201        qt_glProgramLocalParameter4fvARB = 0;
    155202
     203        // GLSL
    156204        qt_glCreateShader = 0;
    157205        qt_glShaderSource = 0;
     206        qt_glShaderBinary = 0;
    158207        qt_glCompileShader = 0;
    159208        qt_glDeleteShader = 0;
     209        qt_glIsShader = 0;
    160210
    161211        qt_glCreateProgram = 0;
     
    165215        qt_glUseProgram = 0;
    166216        qt_glDeleteProgram = 0;
     217        qt_glIsProgram = 0;
    167218
    168219        qt_glGetShaderInfoLog = 0;
    169220        qt_glGetShaderiv = 0;
     221        qt_glGetShaderSource = 0;
    170222        qt_glGetProgramiv = 0;
     223        qt_glGetProgramInfoLog = 0;
    171224
    172225        qt_glGetUniformLocation = 0;
     
    176229        qt_glUniform1fv = 0;
    177230        qt_glUniform1i = 0;
     231        qt_glUniform1iv = 0;
     232        qt_glUniformMatrix2fv = 0;
     233        qt_glUniformMatrix3fv = 0;
     234        qt_glUniformMatrix4fv = 0;
     235        qt_glUniformMatrix2x3fv = 0;
     236        qt_glUniformMatrix2x4fv = 0;
     237        qt_glUniformMatrix3x2fv = 0;
     238        qt_glUniformMatrix3x4fv = 0;
     239        qt_glUniformMatrix4x2fv = 0;
     240        qt_glUniformMatrix4x3fv = 0;
     241
     242        qt_glBindAttribLocation = 0;
     243        qt_glGetAttribLocation = 0;
     244        qt_glVertexAttrib1fv = 0;
     245        qt_glVertexAttrib2fv = 0;
     246        qt_glVertexAttrib3fv = 0;
     247        qt_glVertexAttrib4fv = 0;
     248        qt_glVertexAttribPointer = 0;
     249        qt_glDisableVertexAttribArray = 0;
     250        qt_glEnableVertexAttribArray = 0;
     251
     252        // Extras for GL2 engine:
     253        qt_glActiveTexture = 0;
     254        qt_glStencilOpSeparate = 0;
     255        qt_glBlendColor = 0;
    178256
    179257        qt_glActiveStencilFaceEXT = 0;
    180 
    181258        qt_glMultiTexCoord4f = 0;
    182         qt_glActiveTexture = 0;
    183 
    184 #if !defined(QT_OPENGL_ES_2)
    185         qt_glIsRenderbufferEXT = 0;
    186         qt_glBindRenderbufferEXT = 0;
    187         qt_glDeleteRenderbuffersEXT = 0;
    188         qt_glGenRenderbuffersEXT = 0;
    189         qt_glRenderbufferStorageEXT = 0;
    190         qt_glGetRenderbufferParameterivEXT = 0;
    191         qt_glIsFramebufferEXT = 0;
    192         qt_glBindFramebufferEXT = 0;
    193         qt_glDeleteFramebuffersEXT = 0;
    194         qt_glGenFramebuffersEXT = 0;
    195         qt_glCheckFramebufferStatusEXT = 0;
    196         qt_glFramebufferTexture1DEXT = 0;
    197         qt_glFramebufferTexture2DEXT = 0;
    198         qt_glFramebufferTexture3DEXT = 0;
    199         qt_glFramebufferRenderbufferEXT = 0;
    200         qt_glGetFramebufferAttachmentParameterivEXT = 0;
    201         qt_glGenerateMipmapEXT = 0;
    202 #endif
    203 
    204         qt_glBindBufferARB = 0;
    205         qt_glDeleteBuffersARB = 0;
    206         qt_glGenBuffersARB = 0;
    207         qt_glBufferDataARB = 0;
     259#else
     260        qt_glslResolved = false;
     261
     262        qt_glGetProgramBinaryOES = 0;
     263        qt_glProgramBinaryOES = 0;
     264#endif
     265
     266        // FBOs
     267#if !defined(QT_OPENGL_ES_2)
     268        qt_glIsRenderbuffer = 0;
     269        qt_glBindRenderbuffer = 0;
     270        qt_glDeleteRenderbuffers = 0;
     271        qt_glGenRenderbuffers = 0;
     272        qt_glRenderbufferStorage = 0;
     273        qt_glGetRenderbufferParameteriv = 0;
     274        qt_glIsFramebuffer = 0;
     275        qt_glBindFramebuffer = 0;
     276        qt_glDeleteFramebuffers = 0;
     277        qt_glGenFramebuffers = 0;
     278        qt_glCheckFramebufferStatus = 0;
     279        qt_glFramebufferTexture2D = 0;
     280        qt_glFramebufferRenderbuffer = 0;
     281        qt_glGetFramebufferAttachmentParameteriv = 0;
     282        qt_glGenerateMipmap = 0;
     283#endif
     284        qt_glBlitFramebufferEXT = 0;
     285        qt_glRenderbufferStorageMultisampleEXT = 0;
     286
     287        // Buffer objects:
     288#if !defined(QT_OPENGL_ES_2)
     289        qt_glBindBuffer = 0;
     290        qt_glDeleteBuffers = 0;
     291        qt_glGenBuffers = 0;
     292        qt_glBufferData = 0;
     293#endif
    208294        qt_glMapBufferARB = 0;
    209295        qt_glUnmapBufferARB = 0;
     296
     297#if !defined(QT_OPENGL_ES)
     298        // Texture compression
     299        qt_glCompressedTexImage2DARB = 0;
     300#endif
    210301    }
    211302
     303
     304#if !defined(QT_OPENGL_ES_2)
    212305    _glProgramStringARB qt_glProgramStringARB;
    213306    _glBindProgramARB qt_glBindProgramARB;
     
    219312    _glCreateShader qt_glCreateShader;
    220313    _glShaderSource qt_glShaderSource;
     314    _glShaderBinary qt_glShaderBinary;
    221315    _glCompileShader qt_glCompileShader;
    222316    _glDeleteShader qt_glDeleteShader;
     317    _glIsShader qt_glIsShader;
    223318
    224319    _glCreateProgram qt_glCreateProgram;
     
    228323    _glUseProgram qt_glUseProgram;
    229324    _glDeleteProgram qt_glDeleteProgram;
     325    _glIsProgram qt_glIsProgram;
    230326
    231327    _glGetShaderInfoLog qt_glGetShaderInfoLog;
    232328    _glGetShaderiv qt_glGetShaderiv;
     329    _glGetShaderSource qt_glGetShaderSource;
    233330    _glGetProgramiv qt_glGetProgramiv;
     331    _glGetProgramInfoLog qt_glGetProgramInfoLog;
    234332
    235333    _glGetUniformLocation qt_glGetUniformLocation;
     
    239337    _glUniform1fv qt_glUniform1fv;
    240338    _glUniform1i qt_glUniform1i;
     339    _glUniform1iv qt_glUniform1iv;
     340    _glUniformMatrix2fv qt_glUniformMatrix2fv;
     341    _glUniformMatrix3fv qt_glUniformMatrix3fv;
     342    _glUniformMatrix4fv qt_glUniformMatrix4fv;
     343    _glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
     344    _glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
     345    _glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
     346    _glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
     347    _glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
     348    _glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
     349
     350    _glBindAttribLocation qt_glBindAttribLocation;
     351    _glGetAttribLocation qt_glGetAttribLocation;
     352    _glVertexAttrib1fv qt_glVertexAttrib1fv;
     353    _glVertexAttrib2fv qt_glVertexAttrib2fv;
     354    _glVertexAttrib3fv qt_glVertexAttrib3fv;
     355    _glVertexAttrib4fv qt_glVertexAttrib4fv;
     356    _glVertexAttribPointer qt_glVertexAttribPointer;
     357    _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
     358    _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
     359
     360#else
     361    bool qt_glslResolved;
     362
     363    _glGetProgramBinaryOES qt_glGetProgramBinaryOES;
     364    _glProgramBinaryOES qt_glProgramBinaryOES;
     365#endif
    241366
    242367    _glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
    243 
    244368    _glMultiTexCoord4f qt_glMultiTexCoord4f;
     369
     370#if !defined(QT_OPENGL_ES_2)
     371    // Extras needed for GL2 engine:
    245372    _glActiveTexture qt_glActiveTexture;
    246 
    247 #if !defined(QT_OPENGL_ES_2)
    248     _glIsRenderbufferEXT qt_glIsRenderbufferEXT;
    249     _glBindRenderbufferEXT qt_glBindRenderbufferEXT;
    250     _glDeleteRenderbuffersEXT qt_glDeleteRenderbuffersEXT;
    251     _glGenRenderbuffersEXT qt_glGenRenderbuffersEXT;
    252     _glRenderbufferStorageEXT qt_glRenderbufferStorageEXT;
    253     _glGetRenderbufferParameterivEXT qt_glGetRenderbufferParameterivEXT;
    254     _glIsFramebufferEXT qt_glIsFramebufferEXT;
    255     _glBindFramebufferEXT qt_glBindFramebufferEXT;
    256     _glDeleteFramebuffersEXT qt_glDeleteFramebuffersEXT;
    257     _glGenFramebuffersEXT qt_glGenFramebuffersEXT;
    258     _glCheckFramebufferStatusEXT qt_glCheckFramebufferStatusEXT;
    259     _glFramebufferTexture1DEXT qt_glFramebufferTexture1DEXT;
    260     _glFramebufferTexture2DEXT qt_glFramebufferTexture2DEXT;
    261     _glFramebufferTexture3DEXT qt_glFramebufferTexture3DEXT;
    262     _glFramebufferRenderbufferEXT qt_glFramebufferRenderbufferEXT;
    263     _glGetFramebufferAttachmentParameterivEXT qt_glGetFramebufferAttachmentParameterivEXT;
    264     _glGenerateMipmapEXT qt_glGenerateMipmapEXT;
    265 #endif
    266 
    267     _glBindBufferARB qt_glBindBufferARB;
    268     _glDeleteBuffersARB qt_glDeleteBuffersARB;
    269     _glGenBuffersARB qt_glGenBuffersARB;
    270     _glBufferDataARB qt_glBufferDataARB;
     373    _glStencilOpSeparate qt_glStencilOpSeparate;
     374    _glBlendColor qt_glBlendColor;
     375
     376#endif
     377
     378    // FBOs
     379#if !defined(QT_OPENGL_ES_2)
     380    _glIsRenderbuffer qt_glIsRenderbuffer;
     381    _glBindRenderbuffer qt_glBindRenderbuffer;
     382    _glDeleteRenderbuffers qt_glDeleteRenderbuffers;
     383    _glGenRenderbuffers qt_glGenRenderbuffers;
     384    _glRenderbufferStorage qt_glRenderbufferStorage;
     385    _glGetRenderbufferParameteriv qt_glGetRenderbufferParameteriv;
     386    _glIsFramebuffer qt_glIsFramebuffer;
     387    _glBindFramebuffer qt_glBindFramebuffer;
     388    _glDeleteFramebuffers qt_glDeleteFramebuffers;
     389    _glGenFramebuffers qt_glGenFramebuffers;
     390    _glCheckFramebufferStatus qt_glCheckFramebufferStatus;
     391    _glFramebufferTexture2D qt_glFramebufferTexture2D;
     392    _glFramebufferRenderbuffer qt_glFramebufferRenderbuffer;
     393    _glGetFramebufferAttachmentParameteriv qt_glGetFramebufferAttachmentParameteriv;
     394    _glGenerateMipmap qt_glGenerateMipmap;
     395#endif
     396    _glBlitFramebufferEXT qt_glBlitFramebufferEXT;
     397    _glRenderbufferStorageMultisampleEXT qt_glRenderbufferStorageMultisampleEXT;
     398
     399    // Buffer objects
     400#if !defined(QT_OPENGL_ES_2)
     401    _glBindBuffer qt_glBindBuffer;
     402    _glDeleteBuffers qt_glDeleteBuffers;
     403    _glGenBuffers qt_glGenBuffers;
     404    _glBufferData qt_glBufferData;
     405#endif
    271406    _glMapBufferARB qt_glMapBufferARB;
    272407    _glUnmapBufferARB qt_glUnmapBufferARB;
     408
     409#if !defined(QT_OPENGL_ES)
     410    // Texture compression
     411    _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
     412#endif
    273413};
    274414
     
    286426#ifndef GL_BGRA
    287427#define GL_BGRA 0x80E1
     428#endif
     429
     430#ifndef GL_RGB16
     431#define GL_RGB16 32852
     432#endif
     433
     434#ifndef GL_UNSIGNED_SHORT_5_6_5
     435#define GL_UNSIGNED_SHORT_5_6_5 33635
     436#endif
     437
     438#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
     439#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
    288440#endif
    289441
     
    398550#endif
    399551
     552// GL_EXT_framebuffer_blit
     553#ifndef GL_READ_FRAMEBUFFER_EXT
     554#define GL_READ_FRAMEBUFFER_EXT                                 0x8CA8
     555#endif
     556
     557// GL_EXT_framebuffer_multisample
     558#ifndef GL_RENDERBUFFER_SAMPLES_EXT
     559#define GL_RENDERBUFFER_SAMPLES_EXT                             0x8CAB
     560#endif
     561
     562#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT
     563#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT               0x8D56
     564#endif
     565
     566#ifndef GL_MAX_SAMPLES_EXT
     567#define GL_MAX_SAMPLES_EXT                                      0x8D57
     568#endif
     569
     570#ifndef GL_DRAW_FRAMEBUFFER_EXT
     571#define GL_DRAW_FRAMEBUFFER_EXT                                 0x8CA9
     572#endif
     573
    400574#ifndef GL_EXT_packed_depth_stencil
    401575#define GL_DEPTH_STENCIL_EXT                                    0x84F9
     
    417591#endif
    418592
    419 #define glProgramStringARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramStringARB
    420 #define glBindProgramARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindProgramARB
    421 #define glDeleteProgramsARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgramsARB
    422 #define glGenProgramsARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenProgramsARB
    423 #define glProgramLocalParameter4fvARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramLocalParameter4fvARB
    424 
    425 #define glActiveStencilFaceEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glActiveStencilFaceEXT
    426 
    427 #define glMultiTexCoord4f QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMultiTexCoord4f
    428 
    429 #if !defined(QT_OPENGL_ES_2)
    430 #define glActiveTexture QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glActiveTexture
    431 #endif
    432 
    433 #if !defined(QT_OPENGL_ES_2)
    434 
    435 #define glIsRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsRenderbufferEXT
    436 #define glBindRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindRenderbufferEXT
    437 #define glDeleteRenderbuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteRenderbuffersEXT
    438 #define glGenRenderbuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenRenderbuffersEXT
    439 #define glRenderbufferStorageEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glRenderbufferStorageEXT
    440 #define glGetRenderbufferParameterivEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetRenderbufferParameterivEXT
    441 #define glIsFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsFramebufferEXT
    442 #define glBindFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindFramebufferEXT
    443 #define glDeleteFramebuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteFramebuffersEXT
    444 #define glGenFramebuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenFramebuffersEXT
    445 #define glCheckFramebufferStatusEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCheckFramebufferStatusEXT
    446 #define glFramebufferTexture1DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture1DEXT
    447 #define glFramebufferTexture2DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture2DEXT
    448 #define glFramebufferTexture3DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture3DEXT
    449 #define glFramebufferRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferRenderbufferEXT
    450 #define glGetFramebufferAttachmentParameterivEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetFramebufferAttachmentParameterivEXT
    451 #define glGenerateMipmapEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenerateMipmapEXT
     593#ifndef GL_VERSION_1_4
     594#define GL_CONSTANT_COLOR 0x8001
     595#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
     596#define GL_CONSTANT_ALPHA 0x8003
     597#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
     598#define GL_INCR_WRAP 0x8507
     599#define GL_DECR_WRAP 0x8508
     600#endif
     601
     602#ifndef GL_VERSION_2_0
     603#define GL_FRAGMENT_SHADER 0x8B30
     604#define GL_VERTEX_SHADER 0x8B31
     605#define GL_FLOAT_VEC2 0x8B50
     606#define GL_FLOAT_VEC3 0x8B51
     607#define GL_FLOAT_VEC4 0x8B52
     608#define GL_INT_VEC2 0x8B53
     609#define GL_INT_VEC3 0x8B54
     610#define GL_INT_VEC4 0x8B55
     611#define GL_BOOL 0x8B56
     612#define GL_BOOL_VEC2 0x8B57
     613#define GL_BOOL_VEC3 0x8B58
     614#define GL_BOOL_VEC4 0x8B59
     615#define GL_FLOAT_MAT2 0x8B5A
     616#define GL_FLOAT_MAT3 0x8B5B
     617#define GL_FLOAT_MAT4 0x8B5C
     618#define GL_SAMPLER_1D 0x8B5D
     619#define GL_SAMPLER_2D 0x8B5E
     620#define GL_SAMPLER_3D 0x8B5F
     621#define GL_SAMPLER_CUBE 0x8B60
     622#define GL_COMPILE_STATUS 0x8B81
     623#define GL_LINK_STATUS 0x8B82
     624#define GL_INFO_LOG_LENGTH 0x8B84
     625#define GL_ACTIVE_UNIFORMS 0x8B86
     626#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
     627#define GL_ACTIVE_ATTRIBUTES 0x8B89
     628#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
     629#endif
     630
     631
     632#if !defined(QT_OPENGL_ES_2)
     633#define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB
     634#define glBindProgramARB QGLContextPrivate::extensionFuncs(ctx).qt_glBindProgramARB
     635#define glDeleteProgramsARB QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteProgramsARB
     636#define glGenProgramsARB QGLContextPrivate::extensionFuncs(ctx).qt_glGenProgramsARB
     637#define glProgramLocalParameter4fvARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramLocalParameter4fvARB
     638
     639#define glActiveStencilFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glActiveStencilFaceEXT
     640
     641#define glMultiTexCoord4f QGLContextPrivate::extensionFuncs(ctx).qt_glMultiTexCoord4f
     642
     643#define glActiveTexture QGLContextPrivate::extensionFuncs(ctx).qt_glActiveTexture
     644#endif // !defined(QT_OPENGL_ES_2)
     645
     646
     647// FBOs
     648#if !defined(QT_OPENGL_ES_2)
     649#define glIsRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glIsRenderbuffer
     650#define glBindRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindRenderbuffer
     651#define glDeleteRenderbuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteRenderbuffers
     652#define glGenRenderbuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenRenderbuffers
     653#define glRenderbufferStorage QGLContextPrivate::extensionFuncs(ctx).qt_glRenderbufferStorage
     654#define glGetRenderbufferParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetRenderbufferParameteriv
     655#define glIsFramebuffer QGLContextPrivate::extensionFuncs(ctx).qt_glIsFramebuffer
     656#define glBindFramebuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindFramebuffer
     657#define glDeleteFramebuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteFramebuffers
     658#define glGenFramebuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenFramebuffers
     659#define glCheckFramebufferStatus QGLContextPrivate::extensionFuncs(ctx).qt_glCheckFramebufferStatus
     660#define glFramebufferTexture2D QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTexture2D
     661#define glFramebufferRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferRenderbuffer
     662#define glGetFramebufferAttachmentParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetFramebufferAttachmentParameteriv
     663#define glGenerateMipmap QGLContextPrivate::extensionFuncs(ctx).qt_glGenerateMipmap
     664#endif // QT_OPENGL_ES_2
     665#define glBlitFramebufferEXT QGLContextPrivate::extensionFuncs(ctx).qt_glBlitFramebufferEXT
     666#define glRenderbufferStorageMultisampleEXT QGLContextPrivate::extensionFuncs(ctx).qt_glRenderbufferStorageMultisampleEXT
     667
     668
     669// Buffer objects
     670#if !defined(QT_OPENGL_ES_2)
     671#define glBindBuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindBuffer
     672#define glDeleteBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteBuffers
     673#define glGenBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenBuffers
     674#define glBufferData QGLContextPrivate::extensionFuncs(ctx).qt_glBufferData
     675#endif
     676#define glMapBufferARB QGLContextPrivate::extensionFuncs(ctx).qt_glMapBufferARB
     677#define glUnmapBufferARB QGLContextPrivate::extensionFuncs(ctx).qt_glUnmapBufferARB
     678
     679
     680// GLSL
     681#if !defined(QT_OPENGL_ES_2)
     682
     683#define glCreateShader QGLContextPrivate::extensionFuncs(ctx).qt_glCreateShader
     684#define glShaderSource QGLContextPrivate::extensionFuncs(ctx).qt_glShaderSource
     685#define glShaderBinary QGLContextPrivate::extensionFuncs(ctx).qt_glShaderBinary
     686#define glCompileShader QGLContextPrivate::extensionFuncs(ctx).qt_glCompileShader
     687#define glDeleteShader QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteShader
     688#define glIsShader QGLContextPrivate::extensionFuncs(ctx).qt_glIsShader
     689
     690#define glCreateProgram QGLContextPrivate::extensionFuncs(ctx).qt_glCreateProgram
     691#define glAttachShader QGLContextPrivate::extensionFuncs(ctx).qt_glAttachShader
     692#define glDetachShader QGLContextPrivate::extensionFuncs(ctx).qt_glDetachShader
     693#define glLinkProgram QGLContextPrivate::extensionFuncs(ctx).qt_glLinkProgram
     694#define glUseProgram QGLContextPrivate::extensionFuncs(ctx).qt_glUseProgram
     695#define glDeleteProgram QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteProgram
     696#define glIsProgram QGLContextPrivate::extensionFuncs(ctx).qt_glIsProgram
     697
     698#define glGetShaderInfoLog QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderInfoLog
     699#define glGetShaderiv QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderiv
     700#define glGetShaderSource QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderSource
     701#define glGetProgramiv QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramiv
     702#define glGetProgramInfoLog QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramInfoLog
     703
     704#define glGetUniformLocation QGLContextPrivate::extensionFuncs(ctx).qt_glGetUniformLocation
     705#define glUniform4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform4fv
     706#define glUniform3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform3fv
     707#define glUniform2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform2fv
     708#define glUniform1fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1fv
     709#define glUniform1i QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1i
     710#define glUniform1iv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1iv
     711#define glUniformMatrix2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2fv
     712#define glUniformMatrix3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3fv
     713#define glUniformMatrix4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4fv
     714#define glUniformMatrix2x3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2x3fv
     715#define glUniformMatrix2x4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2x4fv
     716#define glUniformMatrix3x2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3x2fv
     717#define glUniformMatrix3x4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3x4fv
     718#define glUniformMatrix4x2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4x2fv
     719#define glUniformMatrix4x3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4x3fv
     720
     721#define glBindAttribLocation QGLContextPrivate::extensionFuncs(ctx).qt_glBindAttribLocation
     722#define glGetAttribLocation QGLContextPrivate::extensionFuncs(ctx).qt_glGetAttribLocation
     723#define glVertexAttrib1fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib1fv
     724#define glVertexAttrib2fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib2fv
     725#define glVertexAttrib3fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib3fv
     726#define glVertexAttrib4fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib4fv
     727#define glVertexAttribPointer QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttribPointer
     728#define glDisableVertexAttribArray QGLContextPrivate::extensionFuncs(ctx).qt_glDisableVertexAttribArray
     729#define glEnableVertexAttribArray QGLContextPrivate::extensionFuncs(ctx).qt_glEnableVertexAttribArray
    452730
    453731#else // QT_OPENGL_ES_2
    454732
    455 #define glIsRenderbufferEXT glIsRenderbuffer
    456 #define glBindRenderbufferEXT glBindRenderbuffer
    457 #define glDeleteRenderbuffersEXT glDeleteRenderbuffers
    458 #define glGenRenderbuffersEXT glGenRenderbuffers
    459 #define glRenderbufferStorageEXT glRenderbufferStorage
    460 #define glGetRenderbufferParameterivEXT glGetRenderbufferParameteriv
    461 #define glIsFramebufferEXT glIsFramebuffer
    462 #define glBindFramebufferEXT glBindFramebuffer
    463 #define glDeleteFramebuffersEXT glDeleteFramebuffers
    464 #define glGenFramebuffersEXT glGenFramebuffers
    465 #define glCheckFramebufferStatusEXT glCheckFramebufferStatus
    466 #define glFramebufferTexture1DEXT glFramebufferTexture1D
    467 #define glFramebufferTexture2DEXT glFramebufferTexture2D
    468 #define glFramebufferTexture3DEXT glFramebufferTexture3D
    469 #define glFramebufferRenderbufferEXT glFramebufferRenderbuffer
    470 #define glGetFramebufferAttachmentParameterivEXT glGetFramebufferAttachmentParameteriv
    471 #define glGenerateMipmapEXT glGenerateMipmap
     733#define glGetProgramBinaryOES QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramBinaryOES
     734#define glProgramBinaryOES QGLContextPrivate::extensionFuncs(ctx).qt_glProgramBinaryOES
    472735
    473736#endif // QT_OPENGL_ES_2
    474737
    475 #define glBindBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindBufferARB
    476 #define glDeleteBuffersARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteBuffersARB
    477 #define glGenBuffersARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenBuffersARB
    478 #define glBufferDataARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBufferDataARB
    479 #define glMapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMapBufferARB
    480 #define glUnmapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUnmapBufferARB
    481 
    482 #define glCreateShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateShader
    483 #define glShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderSource
    484 #define glCompileShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCompileShader
    485 #define glDeleteShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteShader
    486 
    487 #define glCreateProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateProgram
    488 #define glAttachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glAttachShader
    489 #define glDetachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDetachShader
    490 #define glLinkProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glLinkProgram
    491 #define glUseProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUseProgram
    492 #define glDeleteProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgram
    493 
    494 #define glGetShaderInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderInfoLog
    495 #define glGetShaderiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderiv
    496 #define glGetProgramiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramiv
    497 
    498 #define glGetUniformLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetUniformLocation
    499 #define glUniform4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4fv
    500 #define glUniform3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform3fv
    501 #define glUniform2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2fv
    502 #define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
    503 #define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
     738
     739#if !defined(QT_OPENGL_ES_2)
     740#define glStencilOpSeparate QGLContextPrivate::extensionFuncs(ctx).qt_glStencilOpSeparate
     741#define glBlendColor QGLContextPrivate::extensionFuncs(ctx).qt_glBlendColor
     742#endif
     743
     744#if defined(QT_OPENGL_ES_2)
     745#define glClearDepth glClearDepthf
     746#endif
     747
     748#if !defined(QT_OPENGL_ES)
     749#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
     750#endif
    504751
    505752extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
     
    507754
    508755bool qt_resolve_version_1_3_functions(QGLContext *ctx);
     756bool qt_resolve_version_2_0_functions(QGLContext *ctx);
    509757bool qt_resolve_stencil_face_extension(QGLContext *ctx);
    510758bool qt_resolve_frag_program_extensions(QGLContext *ctx);
  • trunk/src/opengl/qglframebufferobject.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242#include "qglframebufferobject.h"
     43#include "qglframebufferobject_p.h"
    4344
    4445#include <qdebug.h>
    4546#include <private/qgl_p.h>
     47#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     48#include <private/qpaintengineex_opengl2_p.h>
     49#endif
     50
     51#ifndef QT_OPENGL_ES_2
    4652#include <private/qpaintengine_opengl_p.h>
     53#endif
     54
    4755#include <qglframebufferobject.h>
    4856#include <qlibrary.h>
    4957#include <qimage.h>
    5058
     59#ifdef QT_OPENGL_ES_1_CL
     60#include "qgl_cl_p.h"
     61#endif
     62
    5163QT_BEGIN_NAMESPACE
    5264
    5365extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
    5466
    55 #define QGL_FUNC_CONTEXT QGLContext *ctx = d_ptr->ctx;
    56 
     67#define QGL_FUNC_CONTEXT const QGLContext *ctx = d_ptr->fbo_guard.context();
     68#define QGL_FUNCP_CONTEXT const QGLContext *ctx = fbo_guard.context();
     69
     70#ifndef QT_NO_DEBUG
     71#define QT_RESET_GLERROR()                                \
     72{                                                         \
     73    while (glGetError() != GL_NO_ERROR) {}                \
     74}
    5775#define QT_CHECK_GLERROR()                                \
    5876{                                                         \
     
    6381    }                                                     \
    6482}
    65 
    66 class QGLFramebufferObjectPrivate
    67 {
    68 public:
    69     QGLFramebufferObjectPrivate() : depth_stencil_buffer(0), valid(false), bound(false), ctx(0) {}
    70     ~QGLFramebufferObjectPrivate() {}
    71 
    72     void init(const QSize& sz, QGLFramebufferObject::Attachment attachment,
    73               GLenum internal_format, GLenum texture_target);
    74     bool checkFramebufferStatus() const;
    75     GLuint texture;
    76     GLuint fbo;
    77     GLuint depth_stencil_buffer;
    78     GLenum target;
    79     QSize size;
    80     uint valid : 1;
    81     uint bound : 1;
    82     QGLFramebufferObject::Attachment fbo_attachment;
    83     QGLContext *ctx; // for Windows extension ptrs
    84 };
     83#else
     84#define QT_RESET_GLERROR() {}
     85#define QT_CHECK_GLERROR() {}
     86#endif
     87
     88/*!
     89    \class QGLFramebufferObjectFormat
     90    \brief The QGLFramebufferObjectFormat class specifies the format of an OpenGL
     91    framebuffer object.
     92
     93    \since 4.6
     94
     95    \ingroup painting-3D
     96
     97    A framebuffer object has several characteristics:
     98    \list
     99    \i \link setSamples() Number of samples per pixels.\endlink
     100    \i \link setAttachment() Depth and/or stencil attachments.\endlink
     101    \i \link setTextureTarget() Texture target.\endlink
     102    \i \link setInternalTextureFormat() Internal texture format.\endlink
     103    \endlist
     104
     105    Note that the desired attachments or number of samples per pixels might not
     106    be supported by the hardware driver. Call QGLFramebufferObject::format()
     107    after creating a QGLFramebufferObject to find the exact format that was
     108    used to create the frame buffer object.
     109
     110    \sa QGLFramebufferObject
     111*/
     112
     113/*!
     114    \internal
     115*/
     116void QGLFramebufferObjectFormat::detach()
     117{
     118    if (d->ref != 1) {
     119        QGLFramebufferObjectFormatPrivate *newd
     120            = new QGLFramebufferObjectFormatPrivate(d);
     121        if (!d->ref.deref())
     122            delete d;
     123        d = newd;
     124    }
     125}
     126
     127/*!
     128    Creates a QGLFramebufferObjectFormat object for specifying
     129    the format of an OpenGL framebuffer object.
     130
     131    By default the format specifies a non-multisample framebuffer object with no
     132    attachments, texture target \c GL_TEXTURE_2D, and internal format \c GL_RGBA8.
     133    On OpenGL/ES systems, the default internal format is \c GL_RGBA.
     134
     135    \sa samples(), attachment(), target(), internalTextureFormat()
     136*/
     137
     138QGLFramebufferObjectFormat::QGLFramebufferObjectFormat()
     139{
     140    d = new QGLFramebufferObjectFormatPrivate;
     141}
     142
     143/*!
     144    Constructs a copy of \a other.
     145*/
     146
     147QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other)
     148{
     149    d = other.d;
     150    d->ref.ref();
     151}
     152
     153/*!
     154    Assigns \a other to this object.
     155*/
     156
     157QGLFramebufferObjectFormat &QGLFramebufferObjectFormat::operator=(const QGLFramebufferObjectFormat &other)
     158{
     159    if (d != other.d) {
     160        other.d->ref.ref();
     161        if (!d->ref.deref())
     162            delete d;
     163        d = other.d;
     164    }
     165    return *this;
     166}
     167
     168/*!
     169    Destroys the QGLFramebufferObjectFormat.
     170*/
     171QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()
     172{
     173    if (!d->ref.deref())
     174        delete d;
     175}
     176
     177/*!
     178    Sets the number of samples per pixel for a multisample framebuffer object
     179    to \a samples.  The default sample count of 0 represents a regular
     180    non-multisample framebuffer object.
     181
     182    If the desired amount of samples per pixel is not supported by the hardware
     183    then the maximum number of samples per pixel will be used. Note that
     184    multisample framebuffer objects can not be bound as textures. Also, the
     185    \c{GL_EXT_framebuffer_multisample} extension is required to create a
     186    framebuffer with more than one sample per pixel.
     187
     188    \sa samples()
     189*/
     190void QGLFramebufferObjectFormat::setSamples(int samples)
     191{
     192    detach();
     193    d->samples = samples;
     194}
     195
     196/*!
     197    Returns the number of samples per pixel if a framebuffer object
     198    is a multisample framebuffer object. Otherwise, returns 0.
     199    The default value is 0.
     200
     201    \sa setSamples()
     202*/
     203int QGLFramebufferObjectFormat::samples() const
     204{
     205    return d->samples;
     206}
     207
     208/*!
     209    Sets the attachment configuration of a framebuffer object to \a attachment.
     210
     211    \sa attachment()
     212*/
     213void QGLFramebufferObjectFormat::setAttachment(QGLFramebufferObject::Attachment attachment)
     214{
     215    detach();
     216    d->attachment = attachment;
     217}
     218
     219/*!
     220    Returns the configuration of the depth and stencil buffers attached to
     221    a framebuffer object.  The default is QGLFramebufferObject::NoAttachment.
     222
     223    \sa setAttachment()
     224*/
     225QGLFramebufferObject::Attachment QGLFramebufferObjectFormat::attachment() const
     226{
     227    return d->attachment;
     228}
     229
     230/*!
     231    Sets the texture target of the texture attached to a framebuffer object to
     232    \a target. Ignored for multisample framebuffer objects.
     233
     234    \sa textureTarget(), samples()
     235*/
     236void QGLFramebufferObjectFormat::setTextureTarget(GLenum target)
     237{
     238    detach();
     239    d->target = target;
     240}
     241
     242/*!
     243    Returns the texture target of the texture attached to a framebuffer object.
     244    Ignored for multisample framebuffer objects.  The default is
     245    \c GL_TEXTURE_2D.
     246
     247    \sa setTextureTarget(), samples()
     248*/
     249GLenum QGLFramebufferObjectFormat::textureTarget() const
     250{
     251    return d->target;
     252}
     253
     254/*!
     255    Sets the internal format of a framebuffer object's texture or
     256    multisample framebuffer object's color buffer to
     257    \a internalTextureFormat.
     258
     259    \sa internalTextureFormat()
     260*/
     261void QGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat)
     262{
     263    detach();
     264    d->internal_format = internalTextureFormat;
     265}
     266
     267/*!
     268    Returns the internal format of a framebuffer object's texture or
     269    multisample framebuffer object's color buffer.  The default is
     270    \c GL_RGBA8 on desktop OpenGL systems, and \c GL_RGBA on
     271    OpenGL/ES systems.
     272
     273    \sa setInternalTextureFormat()
     274*/
     275GLenum QGLFramebufferObjectFormat::internalTextureFormat() const
     276{
     277    return d->internal_format;
     278}
     279
     280#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
     281/*! \internal */
     282void QGLFramebufferObjectFormat::setTextureTarget(QMacCompatGLenum target)
     283{
     284    detach();
     285    d->target = target;
     286}
     287
     288/*! \internal */
     289void QGLFramebufferObjectFormat::setInternalTextureFormat(QMacCompatGLenum internalTextureFormat)
     290{
     291    detach();
     292    d->internal_format = internalTextureFormat;
     293}
     294#endif
     295
     296/*!
     297    Returns true if all the options of this framebuffer object format
     298    are the same as \a other; otherwise returns false.
     299*/
     300bool QGLFramebufferObjectFormat::operator==(const QGLFramebufferObjectFormat& other) const
     301{
     302    if (d == other.d)
     303        return true;
     304    else
     305        return d->equals(other.d);
     306}
     307
     308/*!
     309    Returns false if all the options of this framebuffer object format
     310    are the same as \a other; otherwise returns true.
     311*/
     312bool QGLFramebufferObjectFormat::operator!=(const QGLFramebufferObjectFormat& other) const
     313{
     314    return !(*this == other);
     315}
     316
     317void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f,
     318                                 QGLFramebufferObject::Attachment attachment)
     319{
     320    fbo = f;
     321    m_thisFBO = fbo->d_func()->fbo(); // This shouldn't be needed
     322
     323    // The context that the fbo was created in may not have depth
     324    // and stencil buffers, but the fbo itself might.
     325    fboFormat = QGLContext::currentContext()->format();
     326    if (attachment == QGLFramebufferObject::CombinedDepthStencil) {
     327        fboFormat.setDepth(true);
     328        fboFormat.setStencil(true);
     329    } else if (attachment == QGLFramebufferObject::Depth) {
     330        fboFormat.setDepth(true);
     331    }
     332}
     333
     334QGLContext *QGLFBOGLPaintDevice::context() const
     335{
     336    QGLContext *fboContext = const_cast<QGLContext *>(fbo->d_ptr->fbo_guard.context());
     337    QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
     338
     339    if (QGLContextPrivate::contextGroup(fboContext) == QGLContextPrivate::contextGroup(currentContext))
     340        return currentContext;
     341    else
     342        return fboContext;
     343}
    85344
    86345bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
    87346{
    88     GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
     347    QGL_FUNCP_CONTEXT;
     348    if (!ctx)
     349        return false;   // Context no longer exists.
     350    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
    89351    switch(status) {
    90352    case GL_NO_ERROR:
     
    118380        qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
    119381        break;
     382    case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
     383        qDebug("QGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
     384        break;
    120385    default:
    121386        qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
     
    125390}
    126391
    127 void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::Attachment attachment,
    128                                        GLenum texture_target, GLenum internal_format)
    129 {
    130     ctx = const_cast<QGLContext *>(QGLContext::currentContext());
     392void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
     393                                       QGLFramebufferObject::Attachment attachment,
     394                                       GLenum texture_target, GLenum internal_format, GLint samples)
     395{
     396    QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
     397    fbo_guard.setContext(ctx);
     398
    131399    bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
    132400    if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
     
    137405    // texture dimensions
    138406
    139     while (glGetError() != GL_NO_ERROR) {} // reset error state
    140     glGenFramebuffersEXT(1, &fbo);
    141     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
     407    QT_RESET_GLERROR(); // reset error state
     408    GLuint fbo = 0;
     409    glGenFramebuffers(1, &fbo);
     410    glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
     411    fbo_guard.setId(fbo);
     412
     413    glDevice.setFBO(q, attachment);
    142414
    143415    QT_CHECK_GLERROR();
    144416    // init texture
    145     glGenTextures(1, &texture);
    146     glBindTexture(target, texture);
    147     glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
    148                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
     417    if (samples == 0) {
     418        glGenTextures(1, &texture);
     419        glBindTexture(target, texture);
     420        glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
     421                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    149422#ifndef QT_OPENGL_ES
    150     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    151     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    152     glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    153     glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     423        glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     424        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     425        glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     426        glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    154427#else
    155     glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    156     glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    157     glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    158     glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    159 #endif
    160     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
    161                               target, texture, 0);
    162 
    163     QT_CHECK_GLERROR();
    164     valid = checkFramebufferStatus();
     428        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     429        glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     430        glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     431        glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     432#endif
     433        glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     434                target, texture, 0);
     435
     436        QT_CHECK_GLERROR();
     437        valid = checkFramebufferStatus();
     438        glBindTexture(target, 0);
     439
     440        color_buffer = 0;
     441    } else {
     442        GLint maxSamples;
     443        glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
     444
     445        samples = qBound(1, int(samples), int(maxSamples));
     446
     447        glGenRenderbuffers(1, &color_buffer);
     448        glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer);
     449        if (glRenderbufferStorageMultisampleEXT) {
     450            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     451                internal_format, size.width(), size.height());
     452        } else {
     453            samples = 0;
     454            glRenderbufferStorage(GL_RENDERBUFFER_EXT, internal_format,
     455                size.width(), size.height());
     456        }
     457
     458        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     459                                     GL_RENDERBUFFER_EXT, color_buffer);
     460
     461        QT_CHECK_GLERROR();
     462        valid = checkFramebufferStatus();
     463
     464        if (valid)
     465            glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples);
     466    }
    165467
    166468    if (attachment == QGLFramebufferObject::CombinedDepthStencil
    167469        && (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
    168470        // depth and stencil buffer needs another extension
    169         glGenRenderbuffersEXT(1, &depth_stencil_buffer);
    170         Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
    171         glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    172         Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
    173         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
     471        glGenRenderbuffers(1, &depth_stencil_buffer);
     472        Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
     473        glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
     474        Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
     475        if (samples != 0 && glRenderbufferStorageMultisampleEXT)
     476            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     477                GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
     478        else
     479            glRenderbufferStorage(GL_RENDERBUFFER_EXT,
     480                GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
     481
    174482        GLint i = 0;
    175         glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
    176         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
     483        glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
     484        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
    177485                                     GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    178         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
     486        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
    179487                                     GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    180488        fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
     489
    181490        valid = checkFramebufferStatus();
    182491        if (!valid)
    183             glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
     492            glDeleteRenderbuffers(1, &depth_stencil_buffer);
    184493    } else if (attachment == QGLFramebufferObject::Depth
    185494               || attachment == QGLFramebufferObject::CombinedDepthStencil)
    186495    {
    187         glGenRenderbuffersEXT(1, &depth_stencil_buffer);
    188         Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
    189         glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    190         Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
     496        glGenRenderbuffers(1, &depth_stencil_buffer);
     497        Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
     498        glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
     499        Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
     500        if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
    191501#ifdef QT_OPENGL_ES
    192502#define GL_DEPTH_COMPONENT16 0x81A5
    193         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
     503            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     504                GL_DEPTH_COMPONENT16, size.width(), size.height());
    194505#else
    195         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
    196 #endif
     506            glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
     507                GL_DEPTH_COMPONENT, size.width(), size.height());
     508#endif
     509        } else {
     510#ifdef QT_OPENGL_ES
     511#define GL_DEPTH_COMPONENT16 0x81A5
     512            glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
     513#else
     514            glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
     515#endif
     516        }
    197517        GLint i = 0;
    198         glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
    199         glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
     518        glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
     519        glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
    200520                                     GL_RENDERBUFFER_EXT, depth_stencil_buffer);
    201521        fbo_attachment = QGLFramebufferObject::Depth;
    202522        valid = checkFramebufferStatus();
    203523        if (!valid)
    204             glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
     524            glDeleteRenderbuffers(1, &depth_stencil_buffer);
    205525    } else {
    206526        fbo_attachment = QGLFramebufferObject::NoAttachment;
    207527    }
    208528
    209     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
     529    glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
    210530    if (!valid) {
    211         glDeleteTextures(1, &texture);
    212         glDeleteFramebuffersEXT(1, &fbo);
     531        if (color_buffer)
     532            glDeleteRenderbuffers(1, &color_buffer);
     533        else
     534            glDeleteTextures(1, &texture);
     535        glDeleteFramebuffers(1, &fbo);
     536        fbo_guard.setId(0);
    213537    }
    214538    QT_CHECK_GLERROR();
     539
     540    format.setTextureTarget(target);
     541    format.setSamples(int(samples));
     542    format.setAttachment(fbo_attachment);
     543    format.setInternalTextureFormat(internal_format);
    215544}
    216545
     
    220549    \since 4.2
    221550
    222     \ingroup multimedia
     551    \ingroup painting-3D
    223552
    224553    The QGLFramebufferObject class encapsulates an OpenGL framebuffer
     
    260589    \endlist
    261590
    262     Note that primitives drawn to a QGLFramebufferObject with QPainter
    263     will only be antialiased if the QPainter::HighQualityAntialiasing
    264     render hint is set. This is because there is currently no support
    265     for the \c{GL_EXT_framebuffer_multisample} extension, which is
    266     required to do multisample based antialiasing. Also note that the
    267     QPainter::HighQualityAntialiasing render hint requires the
    268     \c{GL_ARB_fragment_program} extension to work in OpenGL.
     591    When using a QPainter to paint to a QGLFramebufferObject you should take
     592    care that the QGLFramebufferObject is created with the CombinedDepthStencil
     593    attachment for QPainter to be able to render correctly.
     594    Note that you need to create a QGLFramebufferObject with more than one
     595    sample per pixel for primitives to be antialiased when drawing using a
     596    QPainter. To create a multisample framebuffer object you should use one of
     597    the constructors that take a QGLFramebufferObject parameter, and set the
     598    QGLFramebufferObject::samples() property to a non-zero value.
     599
     600    When painting to a QGLFramebufferObject using QPainter, the state of
     601    the current GL context will be altered by the paint engine to reflect
     602    its needs.  Applications should not rely upon the GL state being reset
     603    to its original conditions, particularly the current shader program,
     604    GL viewport, texture units, and drawing modes.
     605
     606    For multisample framebuffer objects a color render buffer is created,
     607    otherwise a texture with the specified texture target is created.
     608    The color render buffer or texture will have the specified internal
     609    format, and will be bound to the \c GL_COLOR_ATTACHMENT0
     610    attachment in the framebuffer object.
     611
     612    If you want to use a framebuffer object with multisampling enabled
     613    as a texture, you first need to copy from it to a regular framebuffer
     614    object using QGLContext::blitFramebuffer().
    269615
    270616    \sa {Framebuffer Object Example}
     
    308654    can be toggled using one of the overloaded constructors.
    309655
    310     The default internal texture format is \c GL_RGBA8.
     656    The default internal texture format is \c GL_RGBA8 for desktop
     657    OpenGL, and \c GL_RGBA for OpenGL/ES.
    311658
    312659    It is important that you have a current GL context set when
     
    317664*/
    318665
    319 #ifndef QT_OPENGL_ES
    320 #define DEFAULT_FORMAT GL_RGBA8
    321 #else
    322 #define DEFAULT_FORMAT GL_RGBA
    323 #endif
    324 
    325666QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
    326667    : d_ptr(new QGLFramebufferObjectPrivate)
    327668{
    328669    Q_D(QGLFramebufferObject);
    329     d->init(size, NoAttachment, target, DEFAULT_FORMAT);
     670    d->init(this, size, NoAttachment, target, DEFAULT_FORMAT);
    330671}
    331672
     
    336677{
    337678    Q_D(QGLFramebufferObject);
    338     d->init(size, NoAttachment, target, DEFAULT_FORMAT);
     679    d->init(this, size, NoAttachment, target, DEFAULT_FORMAT);
    339680}
    340681#endif
     
    351692{
    352693    Q_D(QGLFramebufferObject);
    353     d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
     694    d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
     695}
     696
     697/*! \overload
     698
     699    Constructs an OpenGL framebuffer object of the given \a size based on the
     700    supplied \a format.
     701*/
     702
     703QGLFramebufferObject::QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format)
     704    : d_ptr(new QGLFramebufferObjectPrivate)
     705{
     706    Q_D(QGLFramebufferObject);
     707    d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),
     708            format.samples());
     709}
     710
     711/*! \overload
     712
     713    Constructs an OpenGL framebuffer object of the given \a width and \a height
     714    based on the supplied \a format.
     715*/
     716
     717QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format)
     718    : d_ptr(new QGLFramebufferObjectPrivate)
     719{
     720    Q_D(QGLFramebufferObject);
     721    d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),
     722            format.internalTextureFormat(), format.samples());
    354723}
    355724
     
    360729{
    361730    Q_D(QGLFramebufferObject);
    362     d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
     731    d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
    363732}
    364733#endif
     
    372741    configuration, \a target the texture target and \a internal_format
    373742    the internal texture format. The default texture target is \c
    374     GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8.
     743    GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8
     744    for desktop OpenGL and \c GL_RGBA for OpenGL/ES.
    375745
    376746    \sa size(), texture(), attachment()
     
    381751{
    382752    Q_D(QGLFramebufferObject);
    383     d->init(QSize(width, height), attachment, target, internal_format);
     753    d->init(this, QSize(width, height), attachment, target, internal_format);
    384754}
    385755
     
    391761{
    392762    Q_D(QGLFramebufferObject);
    393     d->init(QSize(width, height), attachment, target, internal_format);
     763    d->init(this, QSize(width, height), attachment, target, internal_format);
    394764}
    395765#endif
     
    403773    configuration, \a target the texture target and \a internal_format
    404774    the internal texture format. The default texture target is \c
    405     GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8.
     775    GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8
     776    for desktop OpenGL and \c GL_RGBA for OpenGL/ES.
    406777
    407778    \sa size(), texture(), attachment()
     
    412783{
    413784    Q_D(QGLFramebufferObject);
    414     d->init(size, attachment, target, internal_format);
     785    d->init(this, size, attachment, target, internal_format);
    415786}
    416787
     
    422793{
    423794    Q_D(QGLFramebufferObject);
    424     d->init(size, attachment, target, internal_format);
     795    d->init(this, size, attachment, target, internal_format);
    425796}
    426797#endif
     
    436807    QGL_FUNC_CONTEXT;
    437808
    438     if (isValid()
    439         && (d->ctx == QGLContext::currentContext()
    440             || qgl_share_reg()->checkSharing(d->ctx, QGLContext::currentContext())))
    441     {
    442         glDeleteTextures(1, &d->texture);
     809    delete d->engine;
     810
     811    if (isValid() && ctx) {
     812        QGLShareContextScope scope(ctx);
     813        if (d->texture)
     814            glDeleteTextures(1, &d->texture);
     815        if (d->color_buffer)
     816            glDeleteRenderbuffers(1, &d->color_buffer);
    443817        if (d->depth_stencil_buffer)
    444             glDeleteRenderbuffersEXT(1, &d->depth_stencil_buffer);
    445         glDeleteFramebuffersEXT(1, &d->fbo);
    446     }
    447     delete d_ptr;
     818            glDeleteRenderbuffers(1, &d->depth_stencil_buffer);
     819        GLuint fbo = d->fbo();
     820        glDeleteFramebuffers(1, &fbo);
     821    }
    448822}
    449823
     
    455829    The framebuffer can become invalid if the initialization process
    456830    fails, the user attaches an invalid buffer to the framebuffer
    457     object, or a non-power of 2 width/height is specified as the
     831    object, or a non-power of two width/height is specified as the
    458832    texture size if the texture target is \c{GL_TEXTURE_2D}.
     833    The non-power of two limitation does not apply if the OpenGL version
     834    is 2.0 or higher, or if the GL_ARB_texture_non_power_of_two extension
     835    is present.
     836
     837    The framebuffer can also become invalid if the QGLContext that
     838    the framebuffer was created within is destroyed and there are
     839    no other shared contexts that can take over ownership of the
     840    framebuffer.
    459841*/
    460842bool QGLFramebufferObject::isValid() const
    461843{
    462844    Q_D(const QGLFramebufferObject);
    463     return d->valid;
     845    return d->valid && d->fbo_guard.context();
    464846}
    465847
     
    470852    framebuffer to this framebuffer object.
    471853    Returns true upon success, false otherwise.
     854
     855    \sa release()
    472856*/
    473857bool QGLFramebufferObject::bind()
     
    477861    Q_D(QGLFramebufferObject);
    478862    QGL_FUNC_CONTEXT;
    479     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->fbo);
    480     d->bound = d->valid = d->checkFramebufferStatus();
     863    if (!ctx)
     864        return false;   // Context no longer exists.
     865    const QGLContext *current = QGLContext::currentContext();
     866#ifdef QT_DEBUG
     867    if (!current ||
     868        QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
     869    {
     870        qWarning("QGLFramebufferObject::bind() called from incompatible context");
     871    }
     872#endif
     873    glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->fbo());
     874    d->valid = d->checkFramebufferStatus();
     875    if (d->valid && current)
     876        current->d_ptr->current_fbo = d->fbo();
    481877    return d->valid;
    482878}
     
    488884    framebuffer.
    489885    Returns true upon success, false otherwise.
     886
     887    \sa bind()
    490888*/
    491889bool QGLFramebufferObject::release()
     
    493891    if (!isValid())
    494892        return false;
    495     Q_D(QGLFramebufferObject);
    496893    QGL_FUNC_CONTEXT;
    497     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    498     d->valid = d->checkFramebufferStatus();
    499     d->bound = false;
    500     return d->valid;
     894    if (!ctx)
     895        return false;   // Context no longer exists.
     896
     897    const QGLContext *current = QGLContext::currentContext();
     898
     899#ifdef QT_DEBUG
     900    if (!current ||
     901        QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
     902    {
     903        qWarning("QGLFramebufferObject::release() called from incompatible context");
     904    }
     905#endif
     906
     907    if (current) {
     908        current->d_ptr->current_fbo = current->d_ptr->default_fbo;
     909        glBindFramebuffer(GL_FRAMEBUFFER_EXT, current->d_ptr->default_fbo);
     910    }
     911
     912    return true;
    501913}
    502914
     
    507919    rendering target in this framebuffer object. This texture id can
    508920    be bound as a normal texture in your own GL code.
     921
     922    If a multisample framebuffer object is used then the value returned
     923    from this function will be invalid.
    509924*/
    510925GLuint QGLFramebufferObject::texture() const
     
    524939    Q_D(const QGLFramebufferObject);
    525940    return d->size;
     941}
     942
     943/*!
     944    Returns the format of this framebuffer object.
     945*/
     946QGLFramebufferObjectFormat QGLFramebufferObject::format() const
     947{
     948    Q_D(const QGLFramebufferObject);
     949    return d->format;
    526950}
    527951
     
    537961        return QImage();
    538962
    539     const_cast<QGLFramebufferObject *>(this)->bind();
    540     QImage image = qt_gl_read_framebuffer(d->size, d->ctx->format().alpha(), true);
    541     const_cast<QGLFramebufferObject *>(this)->release();
     963    // qt_gl_read_framebuffer doesn't work on a multisample FBO
     964    if (format().samples() != 0) {
     965        QGLFramebufferObject temp(size(), QGLFramebufferObjectFormat());
     966
     967        QRect rect(QPoint(0, 0), size());
     968        blitFramebuffer(&temp, rect, const_cast<QGLFramebufferObject *>(this), rect);
     969
     970        return temp.toImage();
     971    }
     972
     973    bool wasBound = isBound();
     974    if (!wasBound)
     975        const_cast<QGLFramebufferObject *>(this)->bind();
     976    QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != GL_RGB, true);
     977    if (!wasBound)
     978        const_cast<QGLFramebufferObject *>(this)->release();
    542979
    543980    return image;
    544981}
    545982
    546 #if !defined(QT_OPENGL_ES_2)
    547 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
     983#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     984Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
     985#endif
     986
     987#ifndef QT_OPENGL_ES_2
     988Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine)
    548989#endif
    549990
     
    551992QPaintEngine *QGLFramebufferObject::paintEngine() const
    552993{
     994    Q_D(const QGLFramebufferObject);
     995    if (d->engine)
     996        return d->engine;
     997
     998#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     999#if !defined (QT_OPENGL_ES_2)
     1000    if (qt_gl_preferGL2Engine()) {
     1001#endif
     1002        QPaintEngine *engine = qt_buffer_2_engine();
     1003        if (engine->isActive() && engine->paintDevice() != this) {
     1004            d->engine = new QGL2PaintEngineEx;
     1005            return d->engine;
     1006        }
     1007        return engine;
     1008#if !defined (QT_OPENGL_ES_2)
     1009    }
     1010#endif
     1011#endif
     1012
    5531013#if !defined(QT_OPENGL_ES_2)
    554     return qt_buffer_paintengine();
    555 #else
    556     return 0;
     1014    QPaintEngine *engine = qt_buffer_engine();
     1015    if (engine->isActive() && engine->paintDevice() != this) {
     1016        d->engine = new QOpenGLPaintEngine;
     1017        return d->engine;
     1018    }
     1019    return engine;
    5571020#endif
    5581021}
     
    5661029bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
    5671030{
    568     QGLWidget dmy; // needed to detect and init the QGLExtensions object
     1031    QGLExtensions::init();
    5691032    return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
    5701033}
     
    5831046void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
    5841047{
    585     Q_D(QGLFramebufferObject);
    586     d->ctx->drawTexture(target, textureId, textureTarget);
     1048    const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget);
    5871049}
    5881050
     
    5911053void QGLFramebufferObject::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
    5921054{
    593     Q_D(QGLFramebufferObject);
    594     d->ctx->drawTexture(target, textureId, textureTarget);
     1055    const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget);
    5951056}
    5961057#endif
     
    6081069void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
    6091070{
    610     Q_D(QGLFramebufferObject);
    611     d->ctx->drawTexture(point, textureId, textureTarget);
     1071    const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget);
    6121072}
    6131073
     
    6161076void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
    6171077{
    618     Q_D(QGLFramebufferObject);
    619     d->ctx->drawTexture(point, textureId, textureTarget);
    620 }
    621 #endif
    622 
    623 extern int qt_defaultDpi();
     1078    const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget);
     1079}
     1080#endif
     1081
     1082extern int qt_defaultDpiX();
     1083extern int qt_defaultDpiY();
    6241084
    6251085/*! \reimp */
     
    6281088    Q_D(const QGLFramebufferObject);
    6291089
    630     float dpmx = qt_defaultDpi()*100./2.54;
    631     float dpmy = qt_defaultDpi()*100./2.54;
     1090    float dpmx = qt_defaultDpiX()*100./2.54;
     1091    float dpmy = qt_defaultDpiY()*100./2.54;
    6321092    int w = d->size.width();
    6331093    int h = d->size.height();
     
    6521112
    6531113    case PdmDpiX:
    654         return (int)(dpmx * 0.0254);
     1114        return qRound(dpmx * 0.0254);
    6551115
    6561116    case PdmDpiY:
    657         return (int)(dpmy * 0.0254);
     1117        return qRound(dpmy * 0.0254);
    6581118
    6591119    case PdmPhysicalDpiX:
    660         return (int)(dpmx * 0.0254);
     1120        return qRound(dpmx * 0.0254);
    6611121
    6621122    case PdmPhysicalDpiY:
    663         return (int)(dpmy * 0.0254);
     1123        return qRound(dpmy * 0.0254);
    6641124
    6651125    default:
     
    6821142{
    6831143    Q_D(const QGLFramebufferObject);
    684     return d->fbo;
     1144    return d->fbo();
    6851145}
    6861146
    6871147/*! \fn int QGLFramebufferObject::devType() const
    688 
    689     \reimp
     1148    \internal
    6901149*/
    6911150
     
    7141173{
    7151174    Q_D(const QGLFramebufferObject);
    716     return d->bound;
     1175    const QGLContext *current = QGLContext::currentContext();
     1176    return current ? current->d_ptr->current_fbo == d->fbo() : false;
     1177}
     1178
     1179/*!
     1180    \fn bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
     1181
     1182    \since 4.6
     1183
     1184    Returns true if the OpenGL \c{GL_EXT_framebuffer_blit} extension
     1185    is present on this system; otherwise returns false.
     1186
     1187    \sa blitFramebuffer()
     1188*/
     1189bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
     1190{
     1191    QGLExtensions::init();
     1192    return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit);
     1193}
     1194
     1195/*!
     1196    \since 4.6
     1197
     1198    Blits from the \a sourceRect rectangle in the \a source framebuffer
     1199    object to the \a targetRect rectangle in the \a target framebuffer object.
     1200
     1201    If \a source or \a target is 0, the default framebuffer will be used
     1202    instead of a framebuffer object as source or target respectively.
     1203
     1204    The \a buffers parameter should be a mask consisting of any combination of
     1205    \c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and
     1206    \c GL_STENCIL_BUFFER_BIT.  Any buffer type that is not present both
     1207    in the source and target buffers is ignored.
     1208
     1209    The \a sourceRect and \a targetRect rectangles may have different sizes;
     1210    in this case \a buffers should not contain \c GL_DEPTH_BUFFER_BIT or
     1211    \c GL_STENCIL_BUFFER_BIT. The \a filter parameter should be set to
     1212    \c GL_LINEAR or \c GL_NEAREST, and specifies whether linear or nearest
     1213    interpolation should be used when scaling is performed.
     1214
     1215    If \a source equals \a target a copy is performed within the same buffer.
     1216    Results are undefined if the source and target rectangles overlap and
     1217    have different sizes. The sizes must also be the same if any of the
     1218    framebuffer objects are multisample framebuffers.
     1219
     1220    Note that the scissor test will restrict the blit area if enabled.
     1221
     1222    This function will have no effect unless hasOpenGLFramebufferBlit() returns
     1223    true.
     1224
     1225    \sa hasOpenGLFramebufferBlit()
     1226*/
     1227void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
     1228                                           QGLFramebufferObject *source, const QRect &sourceRect,
     1229                                           GLbitfield buffers,
     1230                                           GLenum filter)
     1231{
     1232    if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit))
     1233        return;
     1234
     1235    const QGLContext *ctx = QGLContext::currentContext();
     1236    if (!ctx)
     1237        return;
     1238
     1239    const int height = ctx->device()->height();
     1240
     1241    const int sh = source ? source->height() : height;
     1242    const int th = target ? target->height() : height;
     1243
     1244    const int sx0 = sourceRect.left();
     1245    const int sx1 = sourceRect.left() + sourceRect.width();
     1246    const int sy0 = sh - (sourceRect.top() + sourceRect.height());
     1247    const int sy1 = sh - sourceRect.top();
     1248
     1249    const int tx0 = targetRect.left();
     1250    const int tx1 = targetRect.left() + targetRect.width();
     1251    const int ty0 = th - (targetRect.top() + targetRect.height());
     1252    const int ty1 = th - targetRect.top();
     1253
     1254    glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, source ? source->handle() : 0);
     1255    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, target ? target->handle() : 0);
     1256
     1257    glBlitFramebufferEXT(sx0, sy0, sx1, sy1,
     1258                         tx0, ty0, tx1, ty1,
     1259                         buffers, filter);
     1260
     1261    glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
    7171262}
    7181263
  • trunk/src/opengl/qglframebufferobject.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5353
    5454class QGLFramebufferObjectPrivate;
     55class QGLFramebufferObjectFormat;
    5556
    5657class Q_OPENGL_EXPORT QGLFramebufferObject : public QPaintDevice
     
    7879#endif
    7980
     81    QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format);
     82    QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format);
     83
    8084#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
    8185    QGLFramebufferObject(const QSize &size, QMacCompatGLenum target = GL_TEXTURE_2D);
     
    9094    virtual ~QGLFramebufferObject();
    9195
     96    QGLFramebufferObjectFormat format() const;
     97
    9298    bool isValid() const;
    9399    bool isBound() const;
    94100    bool bind();
    95101    bool release();
     102
    96103    GLuint texture() const;
    97104    QSize size() const;
     
    111118#endif
    112119
     120    static bool hasOpenGLFramebufferBlit();
     121    static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
     122                                QGLFramebufferObject *source, const QRect &sourceRect,
     123                                GLbitfield buffers = GL_COLOR_BUFFER_BIT,
     124                                GLenum filter = GL_NEAREST);
     125
    113126protected:
    114127    int metric(PaintDeviceMetric metric) const;
     
    117130private:
    118131    Q_DISABLE_COPY(QGLFramebufferObject)
    119     QGLFramebufferObjectPrivate *d_ptr;
    120     friend class QGLDrawable;
     132    QScopedPointer<QGLFramebufferObjectPrivate> d_ptr;
     133    friend class QGLPaintDevice;
     134    friend class QGLFBOGLPaintDevice;
     135};
     136
     137class QGLFramebufferObjectFormatPrivate;
     138class Q_OPENGL_EXPORT QGLFramebufferObjectFormat
     139{
     140public:
     141    QGLFramebufferObjectFormat();
     142    QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other);
     143    QGLFramebufferObjectFormat &operator=(const QGLFramebufferObjectFormat &other);
     144    ~QGLFramebufferObjectFormat();
     145
     146    void setSamples(int samples);
     147    int samples() const;
     148
     149    void setAttachment(QGLFramebufferObject::Attachment attachment);
     150    QGLFramebufferObject::Attachment attachment() const;
     151
     152    void setTextureTarget(GLenum target);
     153    GLenum textureTarget() const;
     154
     155    void setInternalTextureFormat(GLenum internalTextureFormat);
     156    GLenum internalTextureFormat() const;
     157
     158#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
     159    void setTextureTarget(QMacCompatGLenum target);
     160    void setInternalTextureFormat(QMacCompatGLenum internalTextureFormat);
     161#endif
     162
     163    bool operator==(const QGLFramebufferObjectFormat& other) const;
     164    bool operator!=(const QGLFramebufferObjectFormat& other) const;
     165
     166private:
     167    QGLFramebufferObjectFormatPrivate *d;
     168
     169    void detach();
    121170};
    122171
  • trunk/src/opengl/qglpixelbuffer.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545    \since 4.1
    4646
    47     \ingroup multimedia
     47    \ingroup painting-3D
    4848
    4949    Rendering into a pbuffer is normally done using full hardware
     
    7777*/
    7878
     79#include <QtCore/qglobal.h>
     80
     81#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     82#include <private/qpaintengineex_opengl2_p.h>
     83#endif
    7984
    8085#include <qglpixelbuffer.h>
     
    8287#include <qimage.h>
    8388
    84 #if !defined(QT_OPENGL_ES_2)
     89#ifndef QT_OPENGL_ES_2
    8590#include <private/qpaintengine_opengl_p.h>
    8691#endif
     
    95100
    96101extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
     102
     103
     104QGLContext* QGLPBufferGLPaintDevice::context() const
     105{
     106    return pbuf->d_func()->qctx;
     107}
     108
     109void QGLPBufferGLPaintDevice::endPaint() {
     110    glFlush();
     111    QGLPaintDevice::endPaint();
     112}
     113
     114void QGLPBufferGLPaintDevice::setPBuffer(QGLPixelBuffer* pb)
     115{
     116    pbuf = pb;
     117}
    97118
    98119void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
     
    106127        qctx = new QGLContext(format);
    107128        qctx->d_func()->sharing = (shareWidget != 0);
    108         if (shareWidget != 0 && shareWidget->d_func()->glcx)
     129        if (shareWidget != 0 && shareWidget->d_func()->glcx) {
    109130            qgl_share_reg()->addShare(qctx, shareWidget->d_func()->glcx);
    110 
     131            shareWidget->d_func()->glcx->d_func()->sharing = true;
     132        }
     133
     134        glDevice.setPBuffer(q);
    111135        qctx->d_func()->paintDevice = q;
    112136        qctx->d_func()->valid = true;
     
    123147#elif defined(QT_OPENGL_ES)
    124148        qctx->d_func()->eglContext = ctx;
     149        qctx->d_func()->eglSurface = pbuf;
    125150#endif
    126151    }
     
    187212    if (current && current != d->qctx)
    188213        current->makeCurrent();
    189     delete d_ptr;
    190214}
    191215
     
    364388}
    365389
    366 #if !defined(QT_OPENGL_ES_2)
    367 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
     390#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
     391Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
     392#endif
     393
     394#ifndef QT_OPENGL_ES_2
     395Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine)
    368396#endif
    369397
     
    371399QPaintEngine *QGLPixelBuffer::paintEngine() const
    372400{
    373 #if !defined(QT_OPENGL_ES_2)
    374     return qt_buffer_paintengine();
     401#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
     402    return qt_buffer_engine();
     403#elif defined(QT_OPENGL_ES_2)
     404    return qt_buffer_2_engine();
    375405#else
    376     return 0;
    377 #endif
    378 }
    379 
    380 extern int qt_defaultDpi();
     406    if (qt_gl_preferGL2Engine())
     407        return qt_buffer_2_engine();
     408    else
     409        return qt_buffer_engine();
     410#endif
     411}
     412
     413extern int qt_defaultDpiX();
     414extern int qt_defaultDpiY();
    381415
    382416/*! \reimp */
     
    385419    Q_D(const QGLPixelBuffer);
    386420
    387     float dpmx = qt_defaultDpi()*100./2.54;
    388     float dpmy = qt_defaultDpi()*100./2.54;
     421    float dpmx = qt_defaultDpiX()*100./2.54;
     422    float dpmy = qt_defaultDpiY()*100./2.54;
    389423    int w = d->req_size.width();
    390424    int h = d->req_size.height();
     
    409443
    410444    case PdmDpiX:
    411         return (int)(dpmx * 0.0254);
     445        return qRound(dpmx * 0.0254);
    412446
    413447    case PdmDpiY:
    414         return (int)(dpmy * 0.0254);
     448        return qRound(dpmy * 0.0254);
    415449
    416450    case PdmPhysicalDpiX:
    417         return (int)(dpmx * 0.0254);
     451        return qRound(dpmx * 0.0254);
    418452
    419453    case PdmPhysicalDpiY:
    420         return (int)(dpmy * 0.0254);
     454        return qRound(dpmy * 0.0254);
    421455
    422456    default:
     
    577611
    578612/*! \fn int QGLPixelBuffer::devType() const
    579     \reimp
     613    \internal
    580614*/
    581615
  • trunk/src/opengl/qglpixelbuffer.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    108108private:
    109109    Q_DISABLE_COPY(QGLPixelBuffer)
    110     QGLPixelBufferPrivate *d_ptr;
     110    QScopedPointer<QGLPixelBufferPrivate> d_ptr;
    111111    friend class QGLDrawable;
    112112    friend class QGLWindowSurface;
     113    friend class QGLPaintDevice;
     114    friend class QGLPBufferGLPaintDevice;
    113115};
    114116
  • trunk/src/opengl/qglpixelbuffer_egl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4848#include <private/qgl_p.h>
    4949
     50#ifdef QT_OPENGL_ES_1_CL
     51#include "qgl_cl_p.h"
     52#endif
     53
    5054QT_BEGIN_NAMESPACE
    5155
     
    6064    // Create the EGL context.
    6165    ctx = new QEglContext();
    62     ctx->setApi(QEglContext::OpenGL);
     66    ctx->setApi(QEgl::OpenGL);
    6367
    6468    // Open the EGL display.
     
    6973    }
    7074
     75    // Find the shared context.
     76    QEglContext *shareContext = 0;
     77    if (shareWidget && shareWidget->d_func()->glcx)
     78        shareContext = shareWidget->d_func()->glcx->d_func()->eglContext;
     79
    7180    // Choose an appropriate configuration.  We use the best format
    7281    // we can find, even if it is greater than the requested format.
    7382    // We try for a pbuffer that is capable of texture rendering if possible.
    74     QEglProperties configProps;
    75     qt_egl_set_format(configProps, QInternal::Pbuffer, f);
    76     configProps.setRenderableType(ctx->api());
    77     bool ok = false;
    78 #if QGL_RENDER_TEXTURE
    79     textureFormat = EGL_TEXTURE_RGBA;
    80     configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
    81     ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
    82     if (!ok) {
    83         // Try again with RGB texture rendering.
    84         textureFormat = EGL_TEXTURE_RGB;
    85         configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA);
    86         configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
    87         ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
     83    textureFormat = EGL_NONE;
     84    if (shareContext) {
     85        // Use the same configuration as the widget we are sharing with.
     86        ctx->setConfig(shareContext->config());
     87#if QGL_RENDER_TEXTURE
     88        EGLint value = EGL_FALSE;
     89        if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA, &value) && value)
     90            textureFormat = EGL_TEXTURE_RGBA;
     91        else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB, &value) && value)
     92            textureFormat = EGL_TEXTURE_RGB;
     93#endif
     94    } else {
     95        QEglProperties configProps;
     96        qt_egl_set_format(configProps, QInternal::Pbuffer, f);
     97        configProps.setRenderableType(ctx->api());
     98        bool ok = false;
     99#if QGL_RENDER_TEXTURE
     100        textureFormat = EGL_TEXTURE_RGBA;
     101        configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
     102        ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
    88103        if (!ok) {
    89             // One last try for a pbuffer with no texture rendering.
    90             configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB);
    91             textureFormat = EGL_NONE;
     104            // Try again with RGB texture rendering.
     105            textureFormat = EGL_TEXTURE_RGB;
     106            configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA);
     107            configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
     108            ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
     109            if (!ok) {
     110                // One last try for a pbuffer with no texture rendering.
     111                configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB);
     112                textureFormat = EGL_NONE;
     113            }
    92114        }
    93     }
    94 #else
    95     textureFormat = EGL_NONE;
    96 #endif
    97     if (!ok) {
    98         if (!ctx->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
    99             delete ctx;
    100             ctx = 0;
    101             return false;
     115#endif
     116        if (!ok) {
     117            if (!ctx->chooseConfig(configProps, QEgl::BestPixelFormat)) {
     118                delete ctx;
     119                ctx = 0;
     120                return false;
     121            }
    102122        }
    103123    }
     
    132152        return false;
    133153    }
    134     ctx->setSurface(pbuf);
    135154
    136155    // Create a new context for the configuration.
    137     QEglContext *shareContext = 0;
    138     if (shareWidget && shareWidget->d_func()->glcx)
    139         shareContext = shareWidget->d_func()->glcx->d_func()->eglContext;
    140156    if (!ctx->createContext(shareContext)) {
    141157        delete ctx;
     
    149165bool QGLPixelBufferPrivate::cleanup()
    150166{
    151     eglDestroySurface(QEglContext::defaultDisplay(0), pbuf);
     167    // No need to destroy "pbuf" here - it is done in QGLContext::reset().
    152168    return true;
    153169}
     
    160176        return false;
    161177    glBindTexture(GL_TEXTURE_2D, texture_id);
    162     return eglBindTexImage(d->ctx->display(), d->ctx->surface(), EGL_BACK_BUFFER);
     178    return eglBindTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER);
    163179#else
    164180    Q_UNUSED(texture_id);
     
    173189    if (d->invalid || d->textureFormat == EGL_NONE || !d->ctx)
    174190        return;
    175     eglReleaseTexImage(d->ctx->display(), d->ctx->surface(), EGL_BACK_BUFFER);
     191    eglReleaseTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER);
    176192#endif
    177193}
     
    189205    else
    190206        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    192     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     207    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     208    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    193209    return texture;
    194210#else
     
    200216{
    201217    // See if we have at least 1 configuration that matches the default format.
    202     QEglContext ctx;
    203     if (!ctx.openDisplay(0))
     218    EGLDisplay dpy = QEglContext::defaultDisplay(0);
     219    if (dpy == EGL_NO_DISPLAY)
    204220        return false;
    205221    QEglProperties configProps;
    206222    qt_egl_set_format(configProps, QInternal::Pbuffer, QGLFormat::defaultFormat());
    207     configProps.setRenderableType(QEglContext::OpenGL);
    208     return ctx.chooseConfig(configProps);
     223    configProps.setRenderableType(QEgl::OpenGL);
     224    do {
     225        EGLConfig cfg = 0;
     226        EGLint matching = 0;
     227        if (eglChooseConfig(dpy, configProps.properties(),
     228                            &cfg, 1, &matching) && matching > 0)
     229            return true;
     230    } while (configProps.reduceConfiguration());
     231    return false;
    209232}
    210233
  • trunk/src/opengl/qglpixelbuffer_mac.mm

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    300300GLuint QGLPixelBuffer::generateDynamicTexture() const
    301301{
     302#ifdef QT_MAC_USE_COCOA
    302303    Q_D(const QGLPixelBuffer);
    303 
    304 #ifdef QT_MAC_USE_COCOA
    305304    NSOpenGLContext *oldContext = [NSOpenGLContext currentContext];
    306305    if (d->share_ctx != oldContext)
  • trunk/src/opengl/qglpixelbuffer_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5959#include "QtOpenGL/qglpixelbuffer.h"
    6060#include <private/qgl_p.h>
     61#include <private/qglpaintdevice_p.h>
    6162
    6263#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
     
    135136
    136137class QEglContext;
     138
     139
     140class QGLPBufferGLPaintDevice : public QGLPaintDevice
     141{
     142public:
     143    virtual QPaintEngine* paintEngine() const {return pbuf->paintEngine();}
     144    virtual QSize size() const {return pbuf->size();}
     145    virtual QGLContext* context() const;
     146    virtual void endPaint();
     147    void setPBuffer(QGLPixelBuffer* pb);
     148private:
     149    QGLPixelBuffer* pbuf;
     150};
    137151
    138152class QGLPixelBufferPrivate {
     
    155169    bool invalid;
    156170    QGLContext *qctx;
     171    QGLPBufferGLPaintDevice glDevice;
    157172    QGLFormat format;
    158173
  • trunk/src/opengl/qglpixelbuffer_win.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/opengl/qglpixelbuffer_x11.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    9494#define glXMakeContextCurrent qt_glXMakeContextCurrent
    9595
     96extern void* qglx_getProcAddress(const char* procName); // in qgl_x11.cpp
     97
    9698static bool qt_resolve_pbuffer_extensions()
    9799{
     
    102104        return false;
    103105
    104 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
    105     void *handle = dlopen(NULL, RTLD_LAZY);
    106     if (handle) {
    107         qt_glXChooseFBConfig = (_glXChooseFBConfig) dlsym(handle, "glXChooseFBConfig");
    108         qt_glXCreateNewContext = (_glXCreateNewContext) dlsym(handle, "glXCreateNewContext");
    109         qt_glXCreatePbuffer = (_glXCreatePbuffer) dlsym(handle, "glXCreatePbuffer");
    110         qt_glXDestroyPbuffer = (_glXDestroyPbuffer) dlsym(handle, "glXDestroyPbuffer");
    111         qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) dlsym(handle, "glXGetFBConfigAttrib");
    112         qt_glXMakeContextCurrent = (_glXMakeContextCurrent) dlsym(handle, "glXMakeContextCurrent");
    113         dlclose(handle);
    114     }
    115     if (!qt_glXChooseFBConfig)
    116 #endif
    117     {
    118         extern const QString qt_gl_library_name();
    119         QLibrary gl(qt_gl_library_name());
    120         qt_glXChooseFBConfig = (_glXChooseFBConfig) gl.resolve("glXChooseFBConfig");
    121         qt_glXCreateNewContext = (_glXCreateNewContext) gl.resolve("glXCreateNewContext");
    122         qt_glXCreatePbuffer = (_glXCreatePbuffer) gl.resolve("glXCreatePbuffer");
    123         qt_glXDestroyPbuffer = (_glXDestroyPbuffer) gl.resolve("glXDestroyPbuffer");
    124         qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) gl.resolve("glXGetFBConfigAttrib");
    125         qt_glXMakeContextCurrent = (_glXMakeContextCurrent) gl.resolve("glXMakeContextCurrent");
    126     }
     106    qt_glXChooseFBConfig = (_glXChooseFBConfig) qglx_getProcAddress("glXChooseFBConfig");
     107    qt_glXCreateNewContext = (_glXCreateNewContext) qglx_getProcAddress("glXCreateNewContext");
     108    qt_glXCreatePbuffer = (_glXCreatePbuffer) qglx_getProcAddress("glXCreatePbuffer");
     109    qt_glXDestroyPbuffer = (_glXDestroyPbuffer) qglx_getProcAddress("glXDestroyPbuffer");
     110    qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) qglx_getProcAddress("glXGetFBConfigAttrib");
     111    qt_glXMakeContextCurrent = (_glXMakeContextCurrent) qglx_getProcAddress("glXMakeContextCurrent");
    127112
    128113    resolved = qt_glXMakeContextCurrent ? true : false;
  • trunk/src/opengl/qglpixmapfilter.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242#include "private/qpixmapfilter_p.h"
     43#include "private/qpixmapdata_gl_p.h"
     44#include "private/qpaintengineex_opengl2_p.h"
     45#include "private/qglengineshadermanager_p.h"
     46#include "private/qpixmapdata_p.h"
     47#include "private/qimagepixmapcleanuphooks_p.h"
    4348#include "qglpixmapfilter_p.h"
    4449#include "qgraphicssystem_gl_p.h"
    4550#include "qpaintengine_opengl_p.h"
    46 
    47 #include "qglpixelbuffer.h"
    48 #include "qglextensions_p.h"
     51#include "qcache.h"
     52
     53#include "qglframebufferobject.h"
     54#include "qglshaderprogram.h"
    4955#include "qgl_p.h"
    5056
    5157#include "private/qapplication_p.h"
    52 
    53 
    54 #ifndef GL_FRAGMENT_SHADER
    55 #define GL_FRAGMENT_SHADER 0x8B30
    56 #endif
    57 
    58 #ifndef GL_COMPILE_STATUS
    59 #define GL_COMPILE_STATUS 0x8B81
    60 #endif
    61 
    62 #ifndef GL_LINK_STATUS
    63 #define GL_LINK_STATUS 0x8B82
    64 #endif
    65 
    66 
    67 
     58#include "private/qdrawhelper_p.h"
     59#include "private/qmemrotate_p.h"
     60#include "private/qmath_p.h"
     61#include "qmath.h"
    6862
    6963QT_BEGIN_NAMESPACE
    7064
     65// qpixmapfilter.cpp
     66void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0);
     67QImage qt_halfScaled(const QImage &source);
    7168
    7269void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const
    7370{
    74     const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, true);
     71    const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, QGLContext::BindOptions(QGLContext::DefaultBindOption | QGLContext::MemoryManagedBindOption));
    7572}
    7673
     
    8077}
    8178
    82 QGLSLProgram::QGLSLProgram(const QString &src)
    83     : ctx(QGLContext::currentContext())
    84 {
    85     if (!qt_resolve_glsl_extensions(const_cast<QGLContext *>(ctx))) {
    86         qWarning("Failed to resolve GLSL functions");
    87         m_valid = false;
    88         return;
    89     }
    90 
    91     m_shader = glCreateShader(GL_FRAGMENT_SHADER);
    92 
    93     const QByteArray src_ba = src.toAscii();
    94     const char *src_cstr = src_ba.constData();
    95 
    96     glShaderSource(m_shader, 1, &src_cstr, 0);
    97     glCompileShader(m_shader);
    98     glGetShaderiv(m_shader, GL_COMPILE_STATUS, &m_valid);
    99     if (!m_valid) {
    100         char data[4096];
    101         GLsizei len;
    102         glGetShaderInfoLog(m_shader, 4096, &len, data);
    103         qWarning("Failed to compile GLSL shader:\n%s\nCODE:\n%s\n", data, src_cstr);
    104         return;
    105     }
    106 
    107     m_program = glCreateProgram();
    108     glAttachShader(m_program, m_shader);
    109     glLinkProgram(m_program);
    110     glGetProgramiv(m_program, GL_LINK_STATUS, &m_valid);
    111     if (!m_valid) {
    112         char data[4096];
    113         GLsizei len;
    114         glGetShaderInfoLog(m_shader, 4096, &len, data);
    115         qWarning("Failed to link GLSL program:\n%s\nCODE:\n%s\n", data, src_cstr);
    116         return;
    117     }
    118 }
    119 
    120 QGLSLProgram::~QGLSLProgram()
    121 {
    122     glDeleteProgram(m_program);
    123     glDeleteShader(m_shader);
    124 }
    125 
    126 bool QGLSLProgram::success() const
    127 {
    128     return m_valid;
    129 }
    130 
    131 void QGLSLProgram::enable()
    132 {
    133     glUseProgram(m_program);
    134 }
    135 
    136 void QGLSLProgram::disable()
    137 {
    138     glUseProgram(0);
    139 }
    140 
    141 typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
    142 typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
    143 typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
    144 typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
    145 typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
    146 typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
    147 
    148 int QGLSLProgram::getUniformLocation(const QString &name)
    149 {
    150     return glGetUniformLocation(m_program, name.toAscii().constData());
    151 }
    152 
    153 void QGLSLProgram::setUniform(int uniform, int value)
    154 {
    155     enable();
    156     glUniform1i(uniform, value);
    157 }
    158 
    159 void QGLSLProgram::setUniform(int uniform, qreal value)
    160 {
    161     enable();
    162     GLfloat v[] = { value };
    163     glUniform1fv(uniform, 1, v);
    164 }
    165 
    166 void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2)
    167 {
    168     enable();
    169     GLfloat v[] = { v1, v2 };
    170     glUniform2fv(uniform, 1, v);
    171 }
    172 
    173 void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3)
    174 {
    175     enable();
    176     GLfloat v[] = { v1, v2, v3 };
    177     glUniform3fv(uniform, 1, v);
    178 }
    179 
    180 void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4)
    181 {
    182     enable();
    183     GLfloat v[] = { v1, v2, v3, v4 };
    184     glUniform4fv(uniform, 1, v);
    185 }
    186 
    187 void QGLSLProgram::setUniform(int uniform, int count, float *v)
    188 {
    189     enable();
    190     glUniform1fv(uniform, count, v);
    191 }
    192 
    193 class QGLPixmapColorizeFilter: public QGLPixmapFilter<QPixmapColorizeFilter>
     79class QGLPixmapColorizeFilter: public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapColorizeFilter>
    19480{
    19581public:
    19682    QGLPixmapColorizeFilter();
    19783
     84    void setUniforms(QGLShaderProgram *program);
     85
    19886protected:
    19987    bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const;
    200 
    201 private:
    202     mutable QGLSLProgram m_program;
    203     uint m_colorUniform;
    20488};
    20589
    206 class QGLPixmapConvolutionFilter: public QGLPixmapFilter<QPixmapConvolutionFilter>
     90class QGLPixmapConvolutionFilter: public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapConvolutionFilter>
    20791{
    20892public:
     
    21094    ~QGLPixmapConvolutionFilter();
    21195
     96    void setUniforms(QGLShaderProgram *program);
     97
    21298protected:
    21399    bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
    214100
    215101private:
    216     QString generateConvolutionShader() const;
    217 
    218     mutable QGLSLProgram *m_program;
    219     mutable uint m_scaleUniform;
    220     mutable uint m_matrixUniform;
    221 
    222     mutable int m_kernelWidth;
    223     mutable int m_kernelHeight;
     102    QByteArray generateConvolutionShader() const;
     103
     104    mutable QSize m_srcSize;
     105    mutable int m_prevKernelSize;
    224106};
    225107
     108class QGLPixmapBlurFilter : public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapBlurFilter>
     109{
     110public:
     111    QGLPixmapBlurFilter();
     112
     113protected:
     114    bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
     115};
     116
     117class QGLPixmapDropShadowFilter : public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapDropShadowFilter>
     118{
     119public:
     120    QGLPixmapDropShadowFilter();
     121
     122    void setUniforms(QGLShaderProgram *program);
     123
     124protected:
     125    bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
     126};
     127
    226128extern QGLWidget *qt_gl_share_widget();
    227129
    228 QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const
    229 {
     130QPixmapFilter *QGL2PaintEngineEx::pixmapFilter(int type, const QPixmapFilter *prototype)
     131{
     132    Q_D(QGL2PaintEngineEx);
    230133    switch (type) {
    231134    case QPixmapFilter::ColorizeFilter:
    232         return new QGLPixmapColorizeFilter;
    233 
     135        if (!d->colorizeFilter)
     136            d->colorizeFilter.reset(new QGLPixmapColorizeFilter);
     137        return d->colorizeFilter.data();
     138
     139    case QPixmapFilter::BlurFilter: {
     140        if (!d->blurFilter)
     141            d->blurFilter.reset(new QGLPixmapBlurFilter());
     142        return d->blurFilter.data();
     143        }
     144
     145    case QPixmapFilter::DropShadowFilter: {
     146        if (!d->dropShadowFilter)
     147            d->dropShadowFilter.reset(new QGLPixmapDropShadowFilter());
     148        return d->dropShadowFilter.data();
     149        }
    234150
    235151    case QPixmapFilter::ConvolutionFilter:
    236         return new QGLPixmapConvolutionFilter;
    237 
    238     default:
    239         return 0;
    240         break;
    241     }
    242     return 0;
    243 }
    244 
    245 #if !defined(QT_OPENGL_ES_2)
    246 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
    247 extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
    248 #endif
    249 
    250 static void qgl_drawTexture(const QRectF &rect, int tx_width, int tx_height, const QRectF & src)
    251 {
    252 #ifndef QT_OPENGL_ES_2  // XXX: needs to be ported
    253 #ifndef QT_OPENGL_ES
    254     glPushAttrib(GL_CURRENT_BIT);
    255 #endif
    256     qreal x1, x2, y1, y2;
    257 
    258     x1 = src.x() / tx_width;
    259     x2 = x1 + src.width() / tx_width;
    260     y1 = 1.0 - ((src.y() / tx_height) + (src.height() / tx_height));
    261     y2 = 1.0 - (src.y() / tx_height);
    262 
    263     q_vertexType vertexArray[4*2];
    264     q_vertexType texCoordArray[4*2];
    265 
    266     qt_add_rect_to_array(rect, vertexArray);
    267     qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
    268 
    269     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    270     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
    271 
    272     glEnableClientState(GL_VERTEX_ARRAY);
    273     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    274     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    275     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    276     glDisableClientState(GL_VERTEX_ARRAY);
    277 
    278 #ifndef QT_OPENGL_ES
    279     glPopAttrib();
    280 #endif
    281 #endif
     152        if (!d->convolutionFilter)
     153            d->convolutionFilter.reset(new QGLPixmapConvolutionFilter);
     154        return d->convolutionFilter.data();
     155
     156    default: break;
     157    }
     158    return QPaintEngineEx::pixmapFilter(type, prototype);
    282159}
    283160
    284161static const char *qt_gl_colorize_filter =
    285         "uniform sampler2D texture;"
    286         "uniform vec3 color;"
    287         "void main(void)"
     162        "uniform lowp vec4 colorizeColor;"
     163        "uniform lowp float colorizeStrength;"
     164        "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords)"
    288165        "{"
    289         "        vec2 coords = gl_TexCoord[0].st;"
    290         "        vec4 src = texture2D(texture, coords);"
    291         "        float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));"
    292         "        vec3 colorizeed = 1.0-((1.0-gray)*(1.0-color));"
    293         "        gl_FragColor = vec4(colorizeed, src.a);"
     166        "        lowp vec4 srcPixel = texture2D(src, srcCoords);"
     167        "        lowp float gray = dot(srcPixel.rgb, vec3(0.212671, 0.715160, 0.072169));"
     168        "        lowp vec3 colorized = 1.0-((1.0-gray)*(1.0-colorizeColor.rgb));"
     169        "        return vec4(mix(srcPixel.rgb, colorized * srcPixel.a, colorizeStrength), srcPixel.a);"
    294170        "}";
    295171
    296172QGLPixmapColorizeFilter::QGLPixmapColorizeFilter()
    297     : m_program(QLatin1String(qt_gl_colorize_filter))
    298 {
    299     m_program.setUniform(m_program.getUniformLocation(QLatin1String("texture")), 0); // GL_TEXTURE_0
    300     m_colorUniform = m_program.getUniformLocation(QLatin1String("color"));
    301 }
    302 
    303 bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
    304 {
    305     bindTexture(src);
    306 
     173{
     174    setSource(qt_gl_colorize_filter);
     175}
     176
     177bool QGLPixmapColorizeFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const
     178{
     179    QGLPixmapColorizeFilter *filter = const_cast<QGLPixmapColorizeFilter *>(this);
     180
     181    filter->setOnPainter(painter);
     182    painter->drawPixmap(pos, src);
     183    filter->removeFromPainter(painter);
     184
     185    return true;
     186}
     187
     188void QGLPixmapColorizeFilter::setUniforms(QGLShaderProgram *program)
     189{
     190    program->setUniformValue("colorizeColor", color());
     191    program->setUniformValue("colorizeStrength", float(strength()));
     192}
     193
     194void QGLPixmapConvolutionFilter::setUniforms(QGLShaderProgram *program)
     195{
     196    const qreal *kernel = convolutionKernel();
     197    int kernelWidth = columns();
     198    int kernelHeight = rows();
     199    int kernelSize = kernelWidth * kernelHeight;
     200
     201    QVarLengthArray<GLfloat> matrix(kernelSize);
     202    QVarLengthArray<GLfloat> offset(kernelSize * 2);
     203
     204    for(int i = 0; i < kernelSize; ++i)
     205        matrix[i] = kernel[i];
     206
     207    for(int y = 0; y < kernelHeight; ++y) {
     208        for(int x = 0; x < kernelWidth; ++x) {
     209            offset[(y * kernelWidth + x) * 2] = x - (kernelWidth / 2);
     210            offset[(y * kernelWidth + x) * 2 + 1] = (kernelHeight / 2) - y;
     211        }
     212    }
     213
     214    const qreal iw = 1.0 / m_srcSize.width();
     215    const qreal ih = 1.0 / m_srcSize.height();
     216    program->setUniformValue("inv_texture_size", iw, ih);
     217    program->setUniformValueArray("matrix", matrix.constData(), kernelSize, 1);
     218    program->setUniformValueArray("offset", offset.constData(), kernelSize, 2);
     219}
     220
     221// generates convolution filter code for arbitrary sized kernel
     222QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const {
     223    QByteArray code;
     224    int kernelWidth = columns();
     225    int kernelHeight = rows();
     226    int kernelSize = kernelWidth * kernelHeight;
     227    code.append("uniform highp vec2 inv_texture_size;\n"
     228                "uniform mediump float matrix[");
     229    code.append(QByteArray::number(kernelSize));
     230    code.append("];\n"
     231                "uniform highp vec2 offset[");
     232    code.append(QByteArray::number(kernelSize));
     233    code.append("];\n");
     234    code.append("lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords) {\n");
     235
     236    code.append("  int i = 0;\n"
     237                "  lowp vec4 sum = vec4(0.0);\n"
     238                "  for (i = 0; i < ");
     239    code.append(QByteArray::number(kernelSize));
     240    code.append("; i++) {\n"
     241                "    sum += matrix[i] * texture2D(src,srcCoords+inv_texture_size*offset[i]);\n"
     242                "  }\n"
     243                "  return sum;\n"
     244                "}");
     245    return code;
     246}
     247
     248QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
     249    : m_prevKernelSize(-1)
     250{
     251}
     252
     253QGLPixmapConvolutionFilter::~QGLPixmapConvolutionFilter()
     254{
     255}
     256
     257bool QGLPixmapConvolutionFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
     258{
     259    QGLPixmapConvolutionFilter *filter = const_cast<QGLPixmapConvolutionFilter *>(this);
     260
     261    m_srcSize = src.size();
     262
     263    int kernelSize = rows() * columns();
     264    if (m_prevKernelSize == -1 || m_prevKernelSize != kernelSize) {
     265        filter->setSource(generateConvolutionShader());
     266        m_prevKernelSize = kernelSize;
     267    }
     268
     269    filter->setOnPainter(painter);
     270    painter->drawPixmap(pos, src, srcRect);
     271    filter->removeFromPainter(painter);
     272
     273    return true;
     274}
     275
     276QGLPixmapBlurFilter::QGLPixmapBlurFilter()
     277{
     278}
     279
     280class QGLBlurTextureInfo
     281{
     282public:
     283    QGLBlurTextureInfo(const QImage &image, GLuint tex, qreal r)
     284        : m_texture(tex)
     285        , m_radius(r)
     286    {
     287        m_paddedImage << image;
     288    }
     289
     290    ~QGLBlurTextureInfo()
     291    {
     292        glDeleteTextures(1, &m_texture);
     293    }
     294
     295    QImage paddedImage(int scaleLevel = 0) const;
     296    GLuint texture() const { return m_texture; }
     297    qreal radius() const { return m_radius; }
     298
     299private:
     300    mutable QList<QImage> m_paddedImage;
     301    GLuint m_texture;
     302    qreal m_radius;
     303};
     304
     305QImage QGLBlurTextureInfo::paddedImage(int scaleLevel) const
     306{
     307    for (int i = m_paddedImage.size() - 1; i <= scaleLevel; ++i)
     308        m_paddedImage << qt_halfScaled(m_paddedImage.at(i));
     309
     310    return m_paddedImage.at(scaleLevel);
     311}
     312
     313class QGLBlurTextureCache : public QObject
     314{
     315public:
     316    static QGLBlurTextureCache *cacheForContext(const QGLContext *context);
     317
     318    QGLBlurTextureCache();
     319    ~QGLBlurTextureCache();
     320
     321    QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap);
     322    bool hasBlurTextureInfo(const QPixmap &pixmap) const;
     323    void insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info);
     324    void clearBlurTextureInfo(const QPixmap &pixmap);
     325
     326    void timerEvent(QTimerEvent *event);
     327
     328private:
     329    static void pixmapDestroyed(QPixmap *pixmap);
     330
     331    QCache<quint64, QGLBlurTextureInfo > cache;
     332
     333    static QList<QGLBlurTextureCache *> blurTextureCaches;
     334
     335    int timerId;
     336};
     337
     338QList<QGLBlurTextureCache *> QGLBlurTextureCache::blurTextureCaches;
     339
     340static void QGLBlurTextureCache_free(void *ptr)
     341{
     342    delete reinterpret_cast<QGLBlurTextureCache *>(ptr);
     343}
     344
     345Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_blur_texture_caches, (QGLBlurTextureCache_free))
     346
     347QGLBlurTextureCache::QGLBlurTextureCache()
     348    : timerId(0)
     349{
     350    cache.setMaxCost(4 * 1024 * 1024);
     351    blurTextureCaches.append(this);
     352}
     353
     354QGLBlurTextureCache::~QGLBlurTextureCache()
     355{
     356    blurTextureCaches.removeAt(blurTextureCaches.indexOf(this));
     357}
     358
     359void QGLBlurTextureCache::timerEvent(QTimerEvent *)
     360{
     361    killTimer(timerId);
     362    timerId = 0;
     363
     364    cache.clear();
     365}
     366
     367QGLBlurTextureCache *QGLBlurTextureCache::cacheForContext(const QGLContext *context)
     368{
     369    QGLBlurTextureCache *p = reinterpret_cast<QGLBlurTextureCache *>(qt_blur_texture_caches()->value(context));
     370    if (!p) {
     371        p = new QGLBlurTextureCache;
     372        qt_blur_texture_caches()->insert(context, p);
     373    }
     374    return p;
     375}
     376
     377QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixmap)
     378{
     379    return cache.take(pixmap.cacheKey());
     380}
     381
     382void QGLBlurTextureCache::clearBlurTextureInfo(const QPixmap &pixmap)
     383{
     384    cache.remove(pixmap.cacheKey());
     385}
     386
     387bool QGLBlurTextureCache::hasBlurTextureInfo(const QPixmap &pixmap) const
     388{
     389    return cache.contains(pixmap.cacheKey());
     390}
     391
     392void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info)
     393{
     394    static bool hookAdded = false;
     395    if (!hookAdded) {
     396        QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(pixmapDestroyed);
     397        hookAdded = true;
     398    }
     399
     400    QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
     401    cache.insert(pixmap.cacheKey(), info, pixmap.width() * pixmap.height());
     402
     403    if (timerId)
     404        killTimer(timerId);
     405
     406    timerId = startTimer(8000);
     407}
     408
     409void QGLBlurTextureCache::pixmapDestroyed(QPixmap *pixmap)
     410{
     411    foreach (QGLBlurTextureCache *cache, blurTextureCaches) {
     412        if (cache->hasBlurTextureInfo(*pixmap))
     413            cache->clearBlurTextureInfo(*pixmap);
     414    }
     415}
     416
     417static const int qAnimatedBlurLevelIncrement = 16;
     418static const int qMaxBlurHalfScaleLevel = 1;
     419
     420static GLuint generateBlurTexture(const QSize &size, GLenum format = GL_RGBA)
     421{
     422    GLuint texture;
     423    glGenTextures(1, &texture);
     424    glBindTexture(GL_TEXTURE_2D, texture);
     425    glTexImage2D(GL_TEXTURE_2D, 0, format, size.width(), size.height(), 0, format,
     426                 GL_UNSIGNED_BYTE, 0);
     427    return texture;
     428}
     429
     430static inline uint nextMultiple(uint x, uint multiplier)
     431{
     432    uint mod = x % multiplier;
     433    if (mod == 0)
     434        return x;
     435    return x + multiplier - mod;
     436}
     437
     438void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride,
     439                       quint32 *dest, int dstStride);
     440
     441bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const
     442{
     443    if (radius() < 1) {
     444        painter->drawPixmap(pos, src);
     445        return true;
     446    }
     447
     448    qreal actualRadius = radius();
     449
     450    QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
     451
     452    QGLBlurTextureCache *blurTextureCache = QGLBlurTextureCache::cacheForContext(ctx);
     453    QGLBlurTextureInfo *info = 0;
     454    int padding = nextMultiple(qCeil(actualRadius), qAnimatedBlurLevelIncrement);
     455    QRect targetRect = src.rect().adjusted(-padding, -padding, padding, padding);
     456
     457    // pad so that we'll be able to half-scale qMaxBlurHalfScaleLevel times
     458    targetRect.setWidth((targetRect.width() + (qMaxBlurHalfScaleLevel-1)) & ~(qMaxBlurHalfScaleLevel-1));
     459    targetRect.setHeight((targetRect.height() + (qMaxBlurHalfScaleLevel-1)) & ~(qMaxBlurHalfScaleLevel-1));
     460
     461    QSize textureSize;
     462
     463    info = blurTextureCache->takeBlurTextureInfo(src);
     464    if (!info || info->radius() < actualRadius) {
     465        QSize paddedSize = targetRect.size() / 2;
     466
     467        QImage padded(paddedSize.height(), paddedSize.width(), QImage::Format_ARGB32_Premultiplied);
     468        padded.fill(0);
     469
     470        if (info) {
     471            int oldPadding = qRound(info->radius());
     472
     473            QPainter p(&padded);
     474            p.setCompositionMode(QPainter::CompositionMode_Source);
     475            p.drawImage((padding - oldPadding) / 2, (padding - oldPadding) / 2, info->paddedImage());
     476            p.end();
     477        } else {
     478            // TODO: combine byteswapping and memrotating into one by declaring
     479            // custom GL_RGBA pixel type and qt_colorConvert template for it
     480            QImage prepadded = qt_halfScaled(src.toImage()).convertToFormat(QImage::Format_ARGB32_Premultiplied);
     481
     482            // byte-swap and memrotates in one go
     483            qt_memrotate90_gl(reinterpret_cast<const quint32*>(prepadded.bits()),
     484                              prepadded.width(), prepadded.height(), prepadded.bytesPerLine(),
     485                              reinterpret_cast<quint32*>(padded.scanLine(padding / 2)) + padding / 2,
     486                              padded.bytesPerLine());
     487        }
     488
     489        delete info;
     490        info = new QGLBlurTextureInfo(padded, generateBlurTexture(paddedSize), padding);
     491
     492        textureSize = paddedSize;
     493    } else {
     494        textureSize = QSize(info->paddedImage().height(), info->paddedImage().width());
     495    }
     496
     497    actualRadius *= qreal(0.5);
     498    int level = 1;
     499    for (; level < qMaxBlurHalfScaleLevel; ++level) {
     500        if (actualRadius <= 16)
     501            break;
     502        actualRadius *= qreal(0.5);
     503    }
     504
     505    const int s = (1 << level);
     506
     507    int prepadding = qRound(info->radius());
     508    padding = qMin(prepadding, qCeil(actualRadius) << level);
     509    targetRect = src.rect().adjusted(-padding, -padding, padding, padding);
     510
     511    targetRect.setWidth(targetRect.width() & ~(s-1));
     512    targetRect.setHeight(targetRect.height() & ~(s-1));
     513
     514    int paddingDelta = (prepadding - padding) >> level;
     515
     516    QRect subRect(paddingDelta, paddingDelta, targetRect.width() >> level, targetRect.height() >> level);
     517    QImage sourceImage = info->paddedImage(level-1);
     518
     519    QImage subImage(subRect.height(), subRect.width(), QImage::Format_ARGB32_Premultiplied);
     520    qt_rectcopy((QRgb *)subImage.bits(), ((QRgb *)sourceImage.scanLine(paddingDelta)) + paddingDelta,
     521                0, 0, subRect.height(), subRect.width(), subImage.bytesPerLine(), sourceImage.bytesPerLine());
     522
     523    GLuint texture = info->texture();
     524
     525    qt_blurImage(subImage, actualRadius, blurHints() & QGraphicsBlurEffect::QualityHint, 1);
     526
     527    // subtract one pixel off the end to prevent the bilinear sampling from sampling uninitialized data
     528    QRect textureSubRect = subImage.rect().adjusted(0, 0, -1, -1);
     529    QRectF targetRectF = QRectF(targetRect).adjusted(0, 0, -targetRect.width() / qreal(textureSize.width()), -targetRect.height() / qreal(textureSize.height()));
     530
     531    glBindTexture(GL_TEXTURE_2D, texture);
     532    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subImage.width(), subImage.height(), GL_RGBA,
     533            GL_UNSIGNED_BYTE, const_cast<const QImage &>(subImage).bits());
     534
     535    QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(painter->paintEngine());
     536    painter->setRenderHint(QPainter::SmoothPixmapTransform);
     537
     538    // texture is flipped on the y-axis
     539    targetRectF = QRectF(targetRectF.x(), targetRectF.bottom(), targetRectF.width(), -targetRectF.height());
     540    engine->drawTexture(targetRectF.translated(pos), texture, textureSize, textureSubRect);
     541
     542    blurTextureCache->insertBlurTextureInfo(src, info);
     543
     544    return true;
     545}
     546
     547static const char *qt_gl_drop_shadow_filter =
     548        "uniform lowp vec4 shadowColor;"
     549        "lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords)"
     550        "{"
     551        "    return shadowColor * texture2D(src, srcCoords.yx).a;"
     552        "}";
     553
     554
     555QGLPixmapDropShadowFilter::QGLPixmapDropShadowFilter()
     556{
     557    setSource(qt_gl_drop_shadow_filter);
     558}
     559
     560bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
     561{
     562    QGLPixmapDropShadowFilter *filter = const_cast<QGLPixmapDropShadowFilter *>(this);
     563
     564    qreal r = blurRadius();
     565    QRectF targetRectUnaligned = QRectF(src.rect()).translated(pos + offset()).adjusted(-r, -r, r, r);
     566    QRect targetRect = targetRectUnaligned.toAlignedRect();
     567
     568    // ensure even dimensions (going to divide by two)
     569    targetRect.setWidth((targetRect.width() + 1) & ~1);
     570    targetRect.setHeight((targetRect.height() + 1) & ~1);
     571
     572    QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
     573    QGLBlurTextureCache *blurTextureCache = QGLBlurTextureCache::cacheForContext(ctx);
     574
     575    QGLBlurTextureInfo *info = blurTextureCache->takeBlurTextureInfo(src);
     576    if (!info || info->radius() != r) {
     577        QImage half = qt_halfScaled(src.toImage().alphaChannel());
     578
     579        qreal rx = r + targetRect.left() - targetRectUnaligned.left();
     580        qreal ry = r + targetRect.top() - targetRectUnaligned.top();
     581
     582        QImage image = QImage(targetRect.size() / 2, QImage::Format_Indexed8);
     583        image.setColorTable(half.colorTable());
     584        image.fill(0);
     585        int dx = qRound(rx * qreal(0.5));
     586        int dy = qRound(ry * qreal(0.5));
     587        qt_rectcopy(image.bits(), half.bits(), dx, dy,
     588                    half.width(), half.height(),
     589                    image.bytesPerLine(), half.bytesPerLine());
     590
     591        qt_blurImage(image, r * qreal(0.5), false, 1);
     592
     593        GLuint texture = generateBlurTexture(image.size(), GL_ALPHA);
     594
     595        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(), image.height(), GL_ALPHA,
     596                        GL_UNSIGNED_BYTE, image.bits());
     597
     598        info = new QGLBlurTextureInfo(image, texture, r);
     599    }
     600
     601    GLuint texture = info->texture();
     602
     603    filter->setOnPainter(painter);
     604
     605    QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(painter->paintEngine());
     606    painter->setRenderHint(QPainter::SmoothPixmapTransform);
     607
     608    engine->drawTexture(targetRect, texture, info->paddedImage().size(), info->paddedImage().rect());
     609
     610    filter->removeFromPainter(painter);
     611
     612    // Now draw the actual pixmap over the top.
     613    painter->drawPixmap(pos, src, srcRect);
     614
     615    blurTextureCache->insertBlurTextureInfo(src, info);
     616
     617    return true;
     618}
     619
     620void QGLPixmapDropShadowFilter::setUniforms(QGLShaderProgram *program)
     621{
    307622    QColor col = color();
    308     m_program.setUniform(m_colorUniform, col.redF(), col.greenF(), col.blueF());
    309 
    310     QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
    311     m_program.enable();
    312     qgl_drawTexture(target, src.width(), src.height(), srcRect);
    313     m_program.disable();
    314 
    315     return true;
    316 }
    317 
    318 // generates convolution filter code for arbitrary sized kernel
    319 QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
    320     QByteArray code;
    321     code.append("uniform sampler2D texture;\n");
    322     code.append("uniform vec2 inv_texture_size;\n");
    323     code.append("uniform float matrix[");
    324     code.append(QByteArray::number(m_kernelWidth * m_kernelHeight));
    325     code.append("];\n");
    326     code.append("vec2 offset[");
    327     code.append(QByteArray::number(m_kernelWidth*m_kernelHeight));
    328     code.append("];\n");
    329     code.append("void main(void) {\n");
    330 
    331     for(int y = 0; y < m_kernelHeight; y++) {
    332         for(int x = 0; x < m_kernelWidth; x++) {
    333             code.append("  offset[");
    334             code.append(QByteArray::number(y * m_kernelWidth + x));
    335             code.append("] = vec2(inv_texture_size.x * ");
    336             code.append(QByteArray::number(x-(int)(m_kernelWidth/2)));
    337             code.append(".0, inv_texture_size.y * ");
    338             code.append(QByteArray::number((int)(m_kernelHeight/2)-y));
    339             code.append(".0)");
    340             code.append(";\n");
    341         }
    342     }
    343 
    344     code.append("  int i = 0;\n");
    345     code.append("  vec2 coords = gl_TexCoord[0].st;\n");
    346     code.append("  vec4 sum = vec4(0.0);\n");
    347     code.append("  for (i = 0; i < ");
    348     code.append(QByteArray::number(m_kernelWidth * m_kernelHeight));
    349     code.append("; i++) {\n");
    350     code.append("    vec4 tmp = texture2D(texture,coords+offset[i]);\n");
    351     code.append("    sum += matrix[i] * tmp;\n");
    352     code.append("  }\n");
    353     code.append("  gl_FragColor = sum;\n");
    354     code.append("}");
    355     return QLatin1String(code);
    356 }
    357 
    358 QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
    359     : m_program(0)
    360     , m_scaleUniform(0)
    361     , m_matrixUniform(0)
    362     , m_kernelWidth(0)
    363     , m_kernelHeight(0)
    364 {
    365 }
    366 
    367 QGLPixmapConvolutionFilter::~QGLPixmapConvolutionFilter()
    368 {
    369     delete m_program;
    370 }
    371 
    372 bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
    373 {
    374     QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
    375 
    376     bindTexture(src);
    377 #ifdef GL_CLAMP
    378     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    379     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    380 #endif
    381     if (!m_program || m_kernelWidth != columns() || m_kernelHeight != rows()) {
    382         delete m_program;
    383 
    384         m_kernelWidth = columns();
    385         m_kernelHeight = rows();
    386 
    387         QString code = generateConvolutionShader();
    388         m_program = new QGLSLProgram(code);
    389         m_scaleUniform = m_program->getUniformLocation(QLatin1String("inv_texture_size"));
    390         m_matrixUniform = m_program->getUniformLocation(QLatin1String("matrix"));
    391     }
    392 
    393     const qreal *kernel = convolutionKernel();
    394     GLfloat *conv = new GLfloat[m_kernelWidth * m_kernelHeight];
    395     for(int i = 0; i < m_kernelWidth * m_kernelHeight; ++i)
    396         conv[i] = kernel[i];
    397 
    398     const qreal iw = 1.0 / src.width();
    399     const qreal ih = 1.0 / src.height();
    400     m_program->setUniform(m_scaleUniform, iw, ih);
    401     m_program->setUniform(m_matrixUniform, m_kernelWidth * m_kernelHeight, conv);
    402 
    403     m_program->enable();
    404     qgl_drawTexture(target, src.width(), src.height(), boundingRectFor(srcRect));
    405     m_program->disable();
    406     return true;
     623    qreal alpha = col.alphaF();
     624    program->setUniformValue("shadowColor", col.redF() * alpha,
     625                                            col.greenF() * alpha,
     626                                            col.blueF() * alpha,
     627                                            alpha);
    407628}
    408629
  • trunk/src/opengl/qglpixmapfilter_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    8888};
    8989
    90 class Q_OPENGL_EXPORT QGLSLProgram
    91 {
    92 public:
    93     QGLSLProgram(const QString &src);
    94     ~QGLSLProgram();
    95 
    96     bool success() const;
    97 
    98     void enable();
    99     void disable();
    100 
    101     int getUniformLocation(const QString &name);
    102 
    103     void setUniform(int uniform, int value);
    104     void setUniform(int uniform, qreal value);
    105     void setUniform(int uniform, qreal v1, qreal v2);
    106     void setUniform(int uniform, qreal v1, qreal v2, qreal v3);
    107     void setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4);
    108     void setUniform(int uniform, int count, float *v);
    109 
    110 private:
    111     GLuint m_shader;
    112     GLuint m_program;
    113 
    114     GLint m_valid;
    115 
    116     const QGLContext *ctx;
    117 };
    118 
    11990QT_END_NAMESPACE
    12091
  • trunk/src/opengl/qgraphicssystem_gl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545#include "private/qpixmapdata_gl_p.h"
    4646#include "private/qwindowsurface_gl_p.h"
     47#include "private/qgl_p.h"
    4748#include <private/qwindowsurface_raster_p.h>
     49
     50#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     51#include "private/qpixmapdata_x11gl_p.h"
     52#include "private/qwindowsurface_x11gl_p.h"
     53#endif
    4854
    4955QT_BEGIN_NAMESPACE
     
    5359QPixmapData *QGLGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
    5460{
     61#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     62    if (type == QPixmapData::PixmapType && QX11GLPixmapData::hasX11GLPixmaps())
     63        return new QX11GLPixmapData();
     64#endif
     65
    5566    return new QGLPixmapData(type);
    5667}
     
    6677#endif
    6778
     79#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     80    if (QX11GLPixmapData::hasX11GLPixmaps())
     81        return new QX11GLWindowSurface(widget);
     82#endif
     83
    6884    return new QGLWindowSurface(widget);
    6985}
  • trunk/src/opengl/qgraphicssystem_gl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
  • trunk/src/opengl/qpaintengine_opengl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
    4040****************************************************************************/
    4141
    42 #include <private/qtextengine_p.h>
    4342#include <qdebug.h>
    4443#include <private/qfontengine_p.h>
     
    5150#include "qgl.h"
    5251#include <private/qgl_p.h>
     52#include <private/qglpaintdevice_p.h>
    5353#include <private/qpainter_p.h>
    5454#include "qmap.h"
     
    5858#include "qvarlengtharray.h"
    5959#include <private/qpainter_p.h>
    60 #include <qglpixelbuffer.h>
    6160#include <private/qglpixelbuffer_p.h>
    6261#include <private/qbezier_p.h>
     
    6463
    6564#include "private/qtessellator_p.h"
    66 #include "private/qwindowsurface_gl_p.h"
    6765
    6866#include "util/fragmentprograms_p.h"
    6967
    7068#ifdef Q_WS_QWS
    71 #include "private/qglpaintdevice_qws_p.h"
    7269#include "private/qglwindowsurface_qws_p.h"
    7370#include "qwsmanager_qws.h"
     
    7976#endif
    8077
    81 #define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(drawable.context());
     78#define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context());
    8279
    8380#include <stdlib.h>
     
    114111static inline void qt_glColor4ubv(unsigned char *col)
    115112{
    116 #ifdef QT_OPENGL_ES
    117         glColor4f(col[0]/255.0, col[1]/255.0, col[2]/255.0, col[3]/255.0);
    118 #else
    119         glColor4ubv(col);
    120 #endif
     113    glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f);
    121114}
    122115
     
    125118    qreal y;
    126119};
    127 
    128 void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
    129 {
    130     qreal left = r.left();
    131     qreal right = r.right();
    132     qreal top = r.top();
    133     qreal bottom = r.bottom();
    134 
    135     array[0] = f2vt(left);
    136     array[1] = f2vt(top);
    137     array[2] = f2vt(right);
    138     array[3] = f2vt(top);
    139     array[4] = f2vt(right);
    140     array[5] = f2vt(bottom);
    141     array[6] = f2vt(left);
    142     array[7] = f2vt(bottom);
    143 }
    144 
    145 void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
    146 {
    147     array[0] = f2vt(x1);
    148     array[1] = f2vt(y1);
    149     array[2] = f2vt(x2);
    150     array[3] = f2vt(y1);
    151     array[4] = f2vt(x2);
    152     array[5] = f2vt(y2);
    153     array[6] = f2vt(x1);
    154     array[7] = f2vt(y2);
    155 }
    156120
    157121struct QGLTrapezoid
     
    189153    trap.bottomRightX += delta.x();
    190154    return trap;
    191 }
    192 
    193 class QGLDrawable {
    194 public:
    195     QGLDrawable() : widget(0), buffer(0), fbo(0)
    196                   , wsurf(0)
    197         {}
    198     inline void setDevice(QPaintDevice *pdev);
    199     inline void swapBuffers();
    200     inline void makeCurrent();
    201     inline void doneCurrent();
    202     inline QSize size() const;
    203     inline QGLFormat format() const;
    204     inline GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
    205     inline GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
    206     inline QColor backgroundColor() const;
    207     inline QGLContext *context() const;
    208     inline bool autoFillBackground() const;
    209 
    210 private:
    211     bool wasBound;
    212     QGLWidget *widget;
    213     QGLPixelBuffer *buffer;
    214     QGLFramebufferObject *fbo;
    215 #ifdef Q_WS_QWS
    216     QWSGLWindowSurface *wsurf;
    217 #else
    218     QGLWindowSurface *wsurf;
    219 #endif
    220 };
    221 
    222 void QGLDrawable::setDevice(QPaintDevice *pdev)
    223 {
    224     wasBound = false;
    225     widget = 0;
    226     buffer = 0;
    227     fbo = 0;
    228 #ifdef Q_WS_QWS
    229     wsurf = 0;
    230 #endif
    231     if (pdev->devType() == QInternal::Widget)
    232         widget = static_cast<QGLWidget *>(pdev);
    233     else if (pdev->devType() == QInternal::Pbuffer)
    234         buffer = static_cast<QGLPixelBuffer *>(pdev);
    235     else if (pdev->devType() == QInternal::FramebufferObject)
    236         fbo = static_cast<QGLFramebufferObject *>(pdev);
    237     else if (pdev->devType() == QInternal::UnknownDevice)
    238 #ifdef Q_WS_QWS
    239         wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
    240 #else
    241         wsurf = static_cast<QGLWindowSurface *>(pdev);
    242 #endif
    243 }
    244 
    245 inline void QGLDrawable::swapBuffers()
    246 {
    247     if (widget) {
    248         if (widget->autoBufferSwap())
    249             widget->swapBuffers();
    250     } else {
    251         glFlush();
    252     }
    253 }
    254 
    255 inline void QGLDrawable::makeCurrent()
    256 {
    257     if (widget)
    258         widget->makeCurrent();
    259     else if (buffer)
    260         buffer->makeCurrent();
    261     else if (wsurf)
    262         wsurf->context()->makeCurrent();
    263     else if (fbo) {
    264         wasBound = fbo->isBound();
    265         if (!wasBound)
    266             fbo->bind();
    267     }
    268 }
    269 
    270 inline void QGLDrawable::doneCurrent()
    271 {
    272     if (fbo && !wasBound)
    273         fbo->release();
    274 }
    275 
    276 inline QSize QGLDrawable::size() const
    277 {
    278     if (widget) {
    279         return QSize(widget->d_func()->glcx->device()->width(),
    280                      widget->d_func()->glcx->device()->height());
    281     } else if (buffer) {
    282         return buffer->size();
    283     } else if (fbo) {
    284         return fbo->size();
    285     } else if (wsurf) {
    286 #ifdef Q_WS_QWS
    287         return wsurf->window()->frameSize();
    288 #else
    289         return QSize(wsurf->width(), wsurf->height());
    290 #endif
    291     }
    292     return QSize();
    293 }
    294 
    295 inline QGLFormat QGLDrawable::format() const
    296 {
    297     if (widget)
    298         return widget->format();
    299     else if (buffer)
    300         return buffer->format();
    301     else if (wsurf)
    302         return wsurf->context()->format();
    303     else if (fbo && QGLContext::currentContext()) {
    304         QGLFormat fmt = QGLContext::currentContext()->format();
    305         fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
    306         fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
    307         return fmt;
    308     }
    309 
    310     return QGLFormat();
    311 }
    312 
    313 inline GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
    314 {
    315     if (widget)
    316         return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
    317     else if (buffer)
    318         return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
    319     else if (fbo && QGLContext::currentContext())
    320         return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
    321     else if (wsurf)
    322         return wsurf->context()->d_func()->bindTexture(image, target, format, true);
    323     return 0;
    324 }
    325 
    326 inline GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
    327 {
    328     if (widget)
    329         return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
    330     else if (buffer)
    331         return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
    332     else if (fbo && QGLContext::currentContext())
    333         return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
    334     else if (wsurf)
    335         return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
    336     return 0;
    337 }
    338 
    339 inline QColor QGLDrawable::backgroundColor() const
    340 {
    341     if (widget)
    342         return widget->palette().brush(widget->backgroundRole()).color();
    343     return QApplication::palette().brush(QPalette::Background).color();
    344 }
    345 
    346 inline QGLContext *QGLDrawable::context() const
    347 {
    348     if (widget)
    349         return widget->d_func()->glcx;
    350     else if (buffer)
    351         return buffer->d_func()->qctx;
    352     else if (fbo)
    353         return const_cast<QGLContext *>(QGLContext::currentContext());
    354     else if (wsurf)
    355         return wsurf->context();
    356     return 0;
    357 }
    358 
    359 inline bool QGLDrawable::autoFillBackground() const
    360 {
    361     if (widget)
    362         return widget->autoFillBackground();
    363     else
    364         return false;
    365155}
    366156
     
    455245    {
    456246        connect(QGLSignalProxy::instance(),
    457                 SIGNAL(aboutToDestroyContext(const QGLContext *)),
    458                 SLOT(cleanupGLContextRefs(const QGLContext *)));
     247                SIGNAL(aboutToDestroyContext(const QGLContext*)),
     248                SLOT(cleanupGLContextRefs(const QGLContext*)));
    459249    }
    460250
     
    493283
    494284private:
    495     QGLDrawable drawable;
     285    QGLPaintDevice* device;
    496286
    497287    QGLFramebufferObject *offscreen;
     
    512302inline void QGLOffscreen::setDevice(QPaintDevice *pdev)
    513303{
    514     drawable.setDevice(pdev);
     304    if (pdev->devType() == QInternal::OpenGL)
     305        device = static_cast<QGLPaintDevice*>(pdev);
     306    else
     307        device = QGLPaintDevice::getDevice(pdev);
     308
     309    if (!device)
     310        return;
    515311
    516312    drawable_fbo = (pdev->devType() == QInternal::FramebufferObject);
     
    536332    initialized = true;
    537333
    538     int dim = qMax(2048, static_cast<int>(qt_next_power_of_two(qMax(drawable.size().width(), drawable.size().height()))));
    539 
    540     bool shared_context = qgl_share_reg()->checkSharing(drawable.context(), ctx);
     334    int dim = qMax(2048, static_cast<int>(qt_next_power_of_two(qMax(device->size().width(), device->size().height()))));
     335
     336    bool shared_context = QGLContext::areSharing(device->context(), ctx);
    541337    bool would_fail = last_failed_size.isValid() &&
    542                       (drawable.size().width() >= last_failed_size.width() ||
    543                        drawable.size().height() >= last_failed_size.height());
     338                      (device->size().width() >= last_failed_size.width() ||
     339                       device->size().height() >= last_failed_size.height());
    544340    bool needs_refresh = dim > mask_dim || !shared_context;
    545341
     
    555351            offscreen = 0;
    556352            mask_dim = 0;
    557             last_failed_size = drawable.size();
     353            last_failed_size = device->size();
    558354        }
    559355    }
    560356
    561357    qt_mask_texture_cache()->setOffscreenSize(offscreenSize());
    562     qt_mask_texture_cache()->setDrawableSize(drawable.size());
    563     ctx = drawable.context();
     358    qt_mask_texture_cache()->setDrawableSize(device->size());
     359    ctx = device->context();
    564360#endif
    565361}
     
    635431
    636432    if (drawable_fbo)
    637         drawable.makeCurrent();
     433        device->ensureActiveTarget(); //###
    638434    else
    639435        offscreen->release();
    640436
    641     QSize sz(drawable.size());
     437    QSize sz(device->size());
    642438    glViewport(0, 0, sz.width(), sz.height());
    643439
     
    662458inline QSize QGLOffscreen::drawableSize() const
    663459{
    664     return drawable.size();
     460    return device->size();
    665461}
    666462
     
    726522        // we have to know when a context is deleted so we can free
    727523        // any program handles it holds
    728         connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext *)),
    729                 SLOT(cleanupPrograms(const QGLContext *)));
     524        connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
     525                SLOT(cleanupPrograms(const QGLContext*)));
    730526
    731527    }
     
    755551        for (int i=0; i<contexts.size(); ++i) {
    756552            const QGLContext *cx = contexts.at(i);
    757             if (cx != ctx && qgl_share_reg()->checkSharing(cx, ctx)) {
     553            if (cx != ctx && QGLContext::areSharing(cx, ctx)) {
    758554                QList<GLProgram> progs = programs.values(cx);
    759555                for (int k=0; k<progs.size(); ++k) {
     
    840636    {
    841637        connect(QGLSignalProxy::instance(),
    842                 SIGNAL(aboutToDestroyContext(const QGLContext *)),
    843                 SLOT(cleanupGLContextRefs(const QGLContext *)));
     638                SIGNAL(aboutToDestroyContext(const QGLContext*)),
     639                SLOT(cleanupGLContextRefs(const QGLContext*)));
    844640    }
    845641
     
    869665        , inverseScale(1)
    870666        , moveToCount(0)
     667        , last_created_state(0)
    871668        , shader_ctx(0)
    872669        , grad_palette(0)
     
    946743    uint has_fast_pen : 1;
    947744    uint use_stencil_method : 1;
    948     uint dirty_stencil : 1;
    949745    uint dirty_drawable_texture : 1;
    950746    uint has_stencil_face_ext : 1;
     
    957753    uint use_emulation : 1;
    958754
     755    QRegion dirty_stencil;
     756
    959757    void updateUseEmulation();
    960758
     
    963761    GLubyte brush_color[4];
    964762    QTransform::TransformationType txop;
    965     QGLDrawable drawable;
     763    QGLPaintDevice* device;
    966764    QGLOffscreen offscreen;
    967765
     
    974772
    975773    void drawImageAsPath(const QRectF &r, const QImage &img, const QRectF &sr);
    976     void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy);
     774    void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset);
    977775
    978776    void drawOffscreenPath(const QPainterPath &path);
     
    994792
    995793    void updateGLMatrix() const;
     794
     795    mutable QPainterState *last_created_state;
    996796
    997797    QGLContext *shader_ctx;
     
    12071007    {
    12081008        connect(QGLSignalProxy::instance(),
    1209                 SIGNAL(aboutToDestroyContext(const QGLContext *)),
    1210                 SLOT(cleanupGLContextRefs(const QGLContext *)));
     1009                SIGNAL(aboutToDestroyContext(const QGLContext*)),
     1010                SLOT(cleanupGLContextRefs(const QGLContext*)));
    12111011    }
    12121012
    12131013    inline GLuint getBuffer(const QGradient &gradient, qreal opacity, QGLContext *ctx) {
    1214         if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx))
     1014        if (buffer_ctx && !QGLContext::areSharing(buffer_ctx, ctx))
    12151015            cleanCache();
    12161016
     
    12741074
    12751075    void cleanCache() {
     1076        QGLShareContextScope scope(buffer_ctx);
    12761077        QGLGradientColorTableHash::const_iterator it = cache.constBegin();
    12771078        for (; it != cache.constEnd(); ++it) {
     
    13711172    Q_UNUSED(g);
    13721173#else
    1373     GLuint texId = qt_opengl_gradient_cache()->getBuffer(g, opacity, drawable.context());
     1174    GLuint texId = qt_opengl_gradient_cache()->getBuffer(g, opacity, device->context());
    13741175    glBindTexture(GL_TEXTURE_1D, texId);
    13751176    grad_palette = texId;
     
    14181219            else if (current_style == Qt::SolidPattern)
    14191220                fragment_brush = FRAGMENT_PROGRAM_BRUSH_SOLID;
    1420             else if (current_style == Qt::TexturePattern)
     1221            else if (current_style == Qt::TexturePattern && !brush.texture().isQBitmap())
    14211222                fragment_brush = FRAGMENT_PROGRAM_BRUSH_TEXTURE;
    14221223            else
     
    14401241    Q_D(QOpenGLPaintEngine);
    14411242
    1442     d->drawable.setDevice(pdev);
     1243    if (pdev->devType() == QInternal::OpenGL)
     1244        d->device = static_cast<QGLPaintDevice*>(pdev);
     1245    else
     1246        d->device = QGLPaintDevice::getDevice(pdev);
     1247
     1248    if (!d->device)
     1249        return false;
     1250
    14431251    d->offscreen.setDevice(pdev);
    14441252    d->has_fast_pen = false;
    14451253    d->inverseScale = 1;
    14461254    d->opacity = 1;
    1447     d->drawable.makeCurrent();
     1255    d->device->beginPaint();
    14481256    d->matrix = QTransform();
    14491257    d->has_antialiasing = false;
    14501258    d->high_quality_antialiasing = false;
    1451     d->dirty_stencil = true;
     1259
     1260    QSize sz(d->device->size());
     1261    d->dirty_stencil = QRect(0, 0, sz.width(), sz.height());
    14521262
    14531263    d->use_emulation = false;
     
    14601270                            && (pdev->devType() != QInternal::Pixmap);
    14611271
    1462     QGLContext *ctx = const_cast<QGLContext *>(d->drawable.context());
     1272    QGLContext *ctx = const_cast<QGLContext *>(d->device->context());
    14631273    if (!ctx) {
    14641274        qWarning() << "QOpenGLPaintEngine: paint device doesn't have a valid GL context.";
     
    14691279        has_frag_program = qt_resolve_frag_program_extensions(ctx) && qt_resolve_version_1_3_functions(ctx);
    14701280
    1471     d->use_stencil_method = d->drawable.format().stencil()
     1281    d->use_stencil_method = d->device->format().stencil()
    14721282                            && (QGLExtensions::glExtensions & QGLExtensions::StencilWrap);
    1473     if (d->drawable.format().directRendering()
     1283    if (d->device->format().directRendering()
    14741284        && (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide))
    14751285        d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);
     
    15371347    d->offscreen.begin();
    15381348
    1539     const QColor &c = d->drawable.backgroundColor();
    1540     glClearColor(c.redF(), c.greenF(), c.blueF(), 1.0);
    1541     if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) {
    1542         GLbitfield clearBits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
    1543 #ifndef QT_OPENGL_ES
    1544         clearBits |= GL_ACCUM_BUFFER_BIT;
    1545 #endif
    1546         glClear(clearBits);
    1547     }
    1548 
    1549     QSize sz(d->drawable.size());
    15501349    glViewport(0, 0, sz.width(), sz.height()); // XXX (Embedded): We need a solution for GLWidgets that draw in a part or a bigger surface...
    15511350    glMatrixMode(GL_PROJECTION);
     
    15641363    d->max_texture_size = ctx->d_func()->maxTextureSize();
    15651364#else
    1566     bool shared_ctx = qgl_share_reg()->checkSharing(d->drawable.context(), d->shader_ctx);
     1365    bool shared_ctx = QGLContext::areSharing(d->device->context(), d->shader_ctx);
    15671366
    15681367    if (shared_ctx) {
     
    15801379            ctx->makeCurrent();
    15811380        }
    1582         d->shader_ctx = d->drawable.context();
     1381        d->shader_ctx = d->device->context();
    15831382        glGenTextures(1, &d->grad_palette);
    15841383
     
    16151414    d->flushDrawQueue();
    16161415    d->offscreen.end();
    1617     QGLContext *ctx = const_cast<QGLContext *>(d->drawable.context());
     1416    QGLContext *ctx = const_cast<QGLContext *>(d->device->context());
    16181417    if (!ctx->d_ptr->internal_context) {
    16191418        glMatrixMode(GL_TEXTURE);
     
    16321431    }
    16331432#endif
    1634     d->drawable.swapBuffers();
    1635     d->drawable.doneCurrent();
     1433    d->device->endPaint();
    16361434    qt_mask_texture_cache()->maintainCache();
    16371435
     
    17961594            QTransform translate(1, 0, 0, 1, -realFocal.x(), -realFocal.y());
    17971595            QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height());
    1798             QTransform inv_matrix = gl_to_qt * matrix.inverted() * brush.transform().inverted() * translate;
     1596            QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y());
     1597            QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate;
    17991598
    18001599            setInvMatrixData(inv_matrix);
     
    18091608            QTransform translate(1, 0, 0, 1, -realCenter.x(), -realCenter.y());
    18101609            QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height());
    1811             QTransform inv_matrix = gl_to_qt * matrix.inverted() * brush.transform().inverted() * translate;
     1610            QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y());
     1611            QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate;
    18121612
    18131613            setInvMatrixData(inv_matrix);
     
    18211621            QTransform translate(1, 0, 0, 1, -realStart.x(), -realStart.y());
    18221622            QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height());
    1823 
    1824             QTransform inv_matrix = gl_to_qt * matrix.inverted() * brush.transform().inverted() * translate;
     1623            QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y());
     1624            QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted() * translate;
    18251625
    18261626            setInvMatrixData(inv_matrix);
     
    18331633            linear_data[2] = 1.0f / (l.x() * l.x() + l.y() * l.y());
    18341634        } else if (style != Qt::SolidPattern) {
    1835             QTransform translate(1, 0, 0, 1, brush_origin.x(), brush_origin.y());
    18361635            QTransform gl_to_qt(1, 0, 0, -1, 0, pdev->height());
    1837 
    1838             QTransform inv_matrix = gl_to_qt * matrix.inverted() * brush.transform().inverted() * translate;
     1636            QTransform m = QTransform(matrix).translate(brush_origin.x(), brush_origin.y());
     1637            QTransform inv_matrix = gl_to_qt * (brush.transform() * m).inverted();
    18391638
    18401639            setInvMatrixData(inv_matrix);
     
    19251724    qreal rightB = trap.bottomRightX + (trap.topRightX - trap.bottomRightX) * reciprocal;
    19261725
    1927     const bool topZero = qFuzzyCompare(topDist + 1, 1);
     1726    const bool topZero = qFuzzyIsNull(topDist);
    19281727
    19291728    reciprocal = topZero ? 1.0 / bottomDist : 1.0 / topDist;
     
    19321731    qreal rightA = topZero ? (trap.bottomRightX - rightB) * reciprocal : (trap.topRightX - rightB) * reciprocal;
    19331732
    1934     qreal invLeftA = qFuzzyCompare(leftA + 1, 1) ? 0.0 : 1.0 / leftA;
    1935     qreal invRightA = qFuzzyCompare(rightA + 1, 1) ? 0.0 : 1.0 / rightA;
     1733    qreal invLeftA = qFuzzyIsNull(leftA) ? 0.0 : 1.0 / leftA;
     1734    qreal invRightA = qFuzzyIsNull(rightA) ? 0.0 : 1.0 / rightA;
    19361735
    19371736    // fragment program needs the negative of invRightA as it mirrors the line
     
    19841783{
    19851784    // On OpenGL ES we convert the trap to 2 triangles
    1986 #ifndef QT_OPENGL_ES_1
     1785#ifndef QT_OPENGL_ES
    19871786    if (size > allocated - 8) {
    19881787#else
     
    19951794    QGLTrapezoid t = toGLTrapezoid(trap);
    19961795
    1997 #ifndef QT_OPENGL_ES_1
    1998     vertices[size++] = t.topLeftX;
    1999     vertices[size++] = t.top;
    2000     vertices[size++] = t.topRightX;
    2001     vertices[size++] = t.top;
    2002     vertices[size++] = t.bottomRightX;
    2003     vertices[size++] = t.bottom;
    2004     vertices[size++] = t.bottomLeftX;
    2005     vertices[size++] = t.bottom;
     1796#ifndef QT_OPENGL_ES
     1797    vertices[size++] = f2vt(t.topLeftX);
     1798    vertices[size++] = f2vt(t.top);
     1799    vertices[size++] = f2vt(t.topRightX);
     1800    vertices[size++] = f2vt(t.top);
     1801    vertices[size++] = f2vt(t.bottomRightX);
     1802    vertices[size++] = f2vt(t.bottom);
     1803    vertices[size++] = f2vt(t.bottomLeftX);
     1804    vertices[size++] = f2vt(t.bottom);
    20061805#else
    20071806    // First triangle
    2008     vertices[size++] = t.topLeftX;
    2009     vertices[size++] = t.top;
    2010     vertices[size++] = t.topRightX;
    2011     vertices[size++] = t.top;
    2012     vertices[size++] = t.bottomRightX;
    2013     vertices[size++] = t.bottom;
     1807    vertices[size++] = f2vt(t.topLeftX);
     1808    vertices[size++] = f2vt(t.top);
     1809    vertices[size++] = f2vt(t.topRightX);
     1810    vertices[size++] = f2vt(t.top);
     1811    vertices[size++] = f2vt(t.bottomRightX);
     1812    vertices[size++] = f2vt(t.bottom);
    20141813
    20151814    // Second triangle
    2016     vertices[size++] = t.bottomLeftX;
    2017     vertices[size++] = t.bottom;
    2018     vertices[size++] = t.topLeftX;
    2019     vertices[size++] = t.top;
    2020     vertices[size++] = t.bottomRightX;
    2021     vertices[size++] = t.bottom;
     1815    vertices[size++] = f2vt(t.bottomLeftX);
     1816    vertices[size++] = f2vt(t.bottom);
     1817    vertices[size++] = f2vt(t.topLeftX);
     1818    vertices[size++] = f2vt(t.top);
     1819    vertices[size++] = f2vt(t.bottomRightX);
     1820    vertices[size++] = f2vt(t.bottom);
    20221821#endif
    20231822}
     
    21491948    Q_Q(QOpenGLPaintEngine);
    21501949
    2151     if (dirty_stencil) {
     1950    QRect rect = dirty_stencil.boundingRect();
     1951
     1952    if (use_system_clip)
     1953        rect = q->systemClip().intersected(dirty_stencil).boundingRect();
     1954
     1955    glStencilMask(~0);
     1956
     1957    if (!rect.isEmpty()) {
    21521958        disableClipping();
    21531959
    2154         if (use_system_clip) {
    2155             glEnable(GL_SCISSOR_TEST);
    2156 
    2157             QRect rect = q->systemClip().boundingRect();
    2158 
    2159             const int left = rect.left();
    2160             const int width = rect.width();
    2161             const int bottom = drawable.size().height() - (rect.bottom() + 1);
    2162             const int height = rect.height();
    2163 
    2164             glScissor(left, bottom, width, height);
    2165         }
     1960        glEnable(GL_SCISSOR_TEST);
     1961
     1962        const int left = rect.left();
     1963        const int width = rect.width();
     1964        const int bottom = device->size().height() - (rect.bottom() + 1);
     1965        const int height = rect.height();
     1966
     1967        glScissor(left, bottom, width, height);
    21661968
    21671969        glClearStencil(0);
    21681970        glClear(GL_STENCIL_BUFFER_BIT);
    2169         dirty_stencil = false;
    2170 
    2171         if (use_system_clip)
    2172             glDisable(GL_SCISSOR_TEST);
     1971        dirty_stencil -= rect;
     1972
     1973        glDisable(GL_SCISSOR_TEST);
    21731974
    21741975        enableClipping();
    21751976    }
    2176 
    2177     glStencilMask(~0);
    21781977
    21791978    // Enable stencil.
     
    22342033    // Enable color writes.
    22352034    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    2236     glStencilMask(0);
     2035    glStencilMask(stencilMask);
    22372036
    22382037    setGradientOps(cbrush, QRectF(QPointF(min_x, min_y), QSizeF(max_x - min_x, max_y - min_y)));
     
    22462045        // Enable stencil func.
    22472046        glStencilFunc(GL_NOTEQUAL, 0, stencilMask);
     2047        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
    22482048        composite(rect);
    22492049    } else {
     
    22522052        // Enable stencil func.
    22532053        glStencilFunc(GL_NOTEQUAL, 0, stencilMask);
     2054        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
    22542055#ifndef QT_OPENGL_ES
    22552056        glBegin(GL_QUADS);
     
    22622063    }
    22632064
    2264     glStencilMask(~0);
    2265     glStencilFunc(GL_ALWAYS, 0, 0);
    2266     glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
    2267 
    2268     // clear all stencil values to 0
    2269     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    2270 
    2271 #ifndef QT_OPENGL_ES
    2272     glBegin(GL_QUADS);
    2273     glVertex2f(min_x, min_y);
    2274     glVertex2f(max_x, min_y);
    2275     glVertex2f(max_x, max_y);
    2276     glVertex2f(min_x, max_y);
    2277     glEnd();
    2278 #endif
    2279 
    2280     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    2281 
    22822065    // Disable stencil writes.
    22832066    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
     
    23322115    d->pen_brush_style = pen.brush().style();
    23332116    d->cpen = pen;
    2334     d->has_pen = (pen_style != Qt::NoPen);
     2117    d->has_pen = (pen_style != Qt::NoPen) && (d->pen_brush_style != Qt::NoBrush);
    23352118    d->updateUseEmulation();
    23362119
     
    24362219    Q_Q(QOpenGLPaintEngine);
    24372220
     2221    ++q->state()->depthClipId;
     2222
    24382223    glDisable(GL_DEPTH_TEST);
    24392224    glDisable(GL_SCISSOR_TEST);
     
    24542239        const int left = fastClip.left();
    24552240        const int width = fastClip.width();
    2456         const int bottom = drawable.size().height() - (fastClip.bottom() + 1);
     2241        const int bottom = device->size().height() - (fastClip.bottom() + 1);
    24572242        const int height = fastClip.height();
    24582243
     
    24612246    }
    24622247
    2463 #ifndef QT_OPENGL_ES
     2248#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_1_CL)
     2249    glClearDepthf(0.0f);
     2250#else
    24642251    glClearDepth(0.0f);
    2465 #else
    2466     glClearDepthf(0.0f);
    24672252#endif
     2253
    24682254    glEnable(GL_DEPTH_TEST);
    24692255    glDepthMask(GL_TRUE);
     
    25242310{
    25252311    Q_Q(QOpenGLPaintEngine);
    2526     if (q->state()->hasClipping)
     2312    if (q->painter()->hasClipping())
    25272313        q->updateClipRegion(q->painter()->clipRegion(), Qt::ReplaceClip);
    25282314    else
     
    25362322    // clipping is only supported when a stencil or depth buffer is
    25372323    // available
    2538     if (!d->drawable.format().depth())
     2324    if (!d->device->format().depth())
    25392325        return;
    25402326
     
    25732359            path = d->matrix.map(path);
    25742360
    2575             if (path.contains(QRectF(QPointF(), d->drawable.size())))
     2361            if (path.contains(QRectF(QPointF(), d->device->size())))
    25762362                isScreenClip = true;
    25772363        }
     
    33013087}
    33023088
     3089extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
     3090extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
     3091
    33033092void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
    33043093{
     
    34463235        qreal width = qAbs(delta.x()) + qAbs(delta.y());
    34473236
    3448         Q_ASSERT(qFuzzyCompare(delta.x() + 1, static_cast<qreal>(1))
    3449                  || qFuzzyCompare(delta.y() + 1, static_cast<qreal>(1)));
     3237        Q_ASSERT(qFuzzyIsNull(delta.x()) || qFuzzyIsNull(delta.y()));
    34503238
    34513239        tessellator.tessellateRect(first, last, width);
     
    35783366    disableClipping();
    35793367
    3580     GLuint program = qt_gl_program_cache()->getProgram(drawable.context(),
     3368    GLuint program = qt_gl_program_cache()->getProgram(device->context(),
    35813369                                                       FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true);
    35823370    QGLPathMaskGenerator maskGenerator(path, matrix, offscreen, program);
     
    37153503            if (d->has_brush) {
    37163504                d->disableClipping();
    3717                 GLuint program = qt_gl_program_cache()->getProgram(d->drawable.context(),
     3505                GLuint program = qt_gl_program_cache()->getProgram(d->device->context(),
    37183506                                                                   FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true);
    3719                 QGLRectMaskGenerator maskGenerator(path, d->matrix, d->offscreen, program);
    3720                 d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d));
     3507
     3508                if (d->matrix.type() >= QTransform::TxProject) {
     3509                    QGLPathMaskGenerator maskGenerator(path, d->matrix, d->offscreen, program);
     3510                    d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d));
     3511                } else {
     3512                    QGLRectMaskGenerator maskGenerator(path, d->matrix, d->offscreen, program);
     3513                    d->addItem(qt_mask_texture_cache()->getMask(maskGenerator, d));
     3514                }
    37213515
    37223516                d->enableClipping();
     
    38933687            // scale or 90 degree rotation?
    38943688            if (d->matrix.type() <= QTransform::TxTranslate
    3895                 || !d->cpen.isCosmetic()
    3896                    && (d->matrix.type() <= QTransform::TxScale
    3897                        || (d->matrix.type() == QTransform::TxRotate
    3898                            && d->matrix.m11() == 0 && d->matrix.m22() == 0))) {
     3689                || (!d->cpen.isCosmetic()
     3690                    && (d->matrix.type() <= QTransform::TxScale
     3691                        || (d->matrix.type() == QTransform::TxRotate
     3692                            && d->matrix.m11() == 0 && d->matrix.m22() == 0)))) {
    38993693                useRects = true;
    39003694                for (int i = 0; i < lineCount; ++i) {
     
    41193913    qreal penWidth = cpen.widthF();
    41203914
    4121     GLuint program = qt_gl_program_cache()->getProgram(drawable.context(),
     3915    GLuint program = qt_gl_program_cache()->getProgram(device->context(),
    41223916                                                       FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA, 0, true);
    41233917    QGLLineMaskGenerator maskGenerator(path, matrix, penWidth == 0 ? 1.0 : penWidth,
     
    41663960        QPen pen = cpen;
    41673961        if (txscale != 1)
    4168             pen.setWidthF(pen.width() * txscale);
     3962            pen.setWidthF(pen.widthF() * txscale);
    41693963        if (use_cache)
    41703964            fillPath(qt_opengl_stroke_cache()->getStrokedPath(temp.map(path), pen));
     
    44094203    qreal scaleY = r.height() / sr.height();
    44104204
    4411     QTransform brush_matrix;
    4412     brush_matrix.translate(r.left(), r.top());
     4205    QTransform brush_matrix = QTransform::fromTranslate(r.left(), r.top());
    44134206    brush_matrix.scale(scaleX, scaleY);
    44144207    brush_matrix.translate(-sr.left(), -sr.top());
     
    44264219}
    44274220
    4428 void QOpenGLPaintEnginePrivate::drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy)
     4221void QOpenGLPaintEnginePrivate::drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy,
     4222                                                     const QPointF &offset)
    44294223{
    44304224    QBrush old_brush = cbrush;
    44314225    QPointF old_brush_origin = brush_origin;
    44324226
    4433     QTransform brush_matrix;
    4434     brush_matrix.translate(r.left(), r.top());
     4227    QTransform brush_matrix = QTransform::fromTranslate(r.left(), r.top());
    44354228    brush_matrix.scale(sx, sy);
     4229    brush_matrix.translate(-offset.x(), -offset.y());
    44364230
    44374231    cbrush = QBrush(img);
     
    45054299        GLenum target = qt_gl_preferredTextureTarget();
    45064300        d->flushDrawQueue();
    4507         d->drawable.bindTexture(pm, target);
    4508         drawTextureRect(pm.width(), pm.height(), r, sr, target);
    4509     }
    4510 }
    4511 
    4512 void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &)
     4301        QGLTexture *tex =
     4302            d->device->context()->d_func()->bindTexture(pm, target, GL_RGBA,
     4303                                                        QGLContext::InternalBindOption);
     4304        drawTextureRect(pm.width(), pm.height(), r, sr, target, tex);
     4305    }
     4306}
     4307
     4308void QOpenGLPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &offset)
    45134309{
    45144310    Q_D(QOpenGLPaintEngine);
     4311    if (pm.depth() == 1) {
     4312        QPixmap tpx(pm.size());
     4313        tpx.fill(Qt::transparent);
     4314        QPainter p(&tpx);
     4315        p.setPen(d->cpen);
     4316        p.drawPixmap(0, 0, pm);
     4317        p.end();
     4318        drawTiledPixmap(r, tpx, offset);
     4319        return;
     4320    }
    45154321
    45164322    QImage scaled;
     
    45204326        int rh = qCeil(r.height());
    45214327        if (rw < pm.width() && rh < pm.height()) {
    4522             drawTiledPixmap(r, pm.copy(0, 0, rw, rh), QPointF());
     4328            drawTiledPixmap(r, pm.copy(0, 0, rw, rh), offset);
    45234329            return;
    45244330        }
     
    45294335    if (d->composition_mode > QPainter::CompositionMode_Plus || (d->high_quality_antialiasing && !d->isFastRect(r))) {
    45304336        if (scaled.isNull())
    4531             d->drawTiledImageAsPath(r, pm.toImage(), 1, 1);
     4337            d->drawTiledImageAsPath(r, pm.toImage(), 1, 1, offset);
    45324338        else {
    45334339            const qreal sx = pm.width() / qreal(scaled.width());
    45344340            const qreal sy = pm.height() / qreal(scaled.height());
    4535             d->drawTiledImageAsPath(r, scaled, sx, sy);
     4341            d->drawTiledImageAsPath(r, scaled, sx, sy, offset);
    45364342        }
    45374343    } else {
    45384344        d->flushDrawQueue();
    45394345
     4346        QGLTexture *tex;
    45404347        if (scaled.isNull())
    4541             d->drawable.bindTexture(pm);
     4348            tex = d->device->context()->d_func()->bindTexture(pm, GL_TEXTURE_2D, GL_RGBA,
     4349                                                              QGLContext::InternalBindOption);
    45424350        else
    4543             d->drawable.bindTexture(scaled);
     4351            tex = d->device->context()->d_func()->bindTexture(scaled, GL_TEXTURE_2D, GL_RGBA,
     4352                                                              QGLContext::InternalBindOption);
    45444353        updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, d->use_smooth_pixmap_transform);
    45454354
     
    45564365        // Rotate the texture so that it is aligned correctly and the
    45574366        // wrapping is done correctly
    4558         glMatrixMode(GL_TEXTURE);
    4559         glPushMatrix();
    4560         glRotatef(180.0, 0.0, 1.0, 0.0);
    4561         glRotatef(180.0, 0.0, 0.0, 1.0);
     4367        if (tex->options & QGLContext::InvertedYBindOption) {
     4368            glMatrixMode(GL_TEXTURE);
     4369            glPushMatrix();
     4370            glRotatef(180.0, 0.0, 1.0, 0.0);
     4371            glRotatef(180.0, 0.0, 0.0, 1.0);
     4372        }
    45624373
    45634374        q_vertexType vertexArray[4*2];
    45644375        q_vertexType texCoordArray[4*2];
    45654376
     4377        double offset_x = offset.x() / pm.width();
     4378        double offset_y = offset.y() / pm.height();
     4379
    45664380        qt_add_rect_to_array(r, vertexArray);
    4567         qt_add_texcoords_to_array(0, 0, tc_w, tc_h, texCoordArray);
     4381        qt_add_texcoords_to_array(offset_x, offset_y,
     4382                                  tc_w + offset_x, tc_h + offset_y, texCoordArray);
    45684383
    45694384        glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
     
    45754390        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    45764391        glDisableClientState(GL_VERTEX_ARRAY);
    4577         glPopMatrix();
     4392        if (tex->options & QGLContext::InvertedYBindOption)
     4393            glPopMatrix();
    45784394
    45794395        glDisable(GL_TEXTURE_2D);
     
    46114427        GLenum target = qt_gl_preferredTextureTarget();
    46124428        d->flushDrawQueue();
    4613         d->drawable.bindTexture(image, target);
    4614         drawTextureRect(image.width(), image.height(), r, sr, target);
     4429        QGLTexture *tex =
     4430            d->device->context()->d_func()->bindTexture(image, target, GL_RGBA,
     4431                                                        QGLContext::InternalBindOption);
     4432        drawTextureRect(image.width(), image.height(), r, sr, target, tex);
    46154433    }
    46164434}
    46174435
    46184436void QOpenGLPaintEngine::drawTextureRect(int tx_width, int tx_height, const QRectF &r,
    4619                                          const QRectF &sr, GLenum target)
     4437                                         const QRectF &sr, GLenum target, QGLTexture *tex)
    46204438{
    46214439    Q_D(QOpenGLPaintEngine);
     
    46324450        x1 = sr.x() / tx_width;
    46334451        x2 = x1 + sr.width() / tx_width;
    4634         y1 = 1.0 - (sr.bottom() / tx_height);
    4635         y2 = 1.0 - (sr.y() / tx_height);
     4452        if (tex->options & QGLContext::InvertedYBindOption) {
     4453            y1 = 1 - (sr.bottom() / tx_height);
     4454            y2 = 1 - (sr.y() / tx_height);
     4455        } else {
     4456            y1 = sr.bottom() / tx_height;
     4457            y2 = sr.y() / tx_height;
     4458        }
    46364459    } else {
    46374460        x1 = sr.x();
    46384461        x2 = sr.right();
    4639         y1 = tx_height - sr.bottom();
    4640         y2 = tx_height - sr.y();
     4462        y1 = sr.bottom();
     4463        y2 = sr.y();
    46414464    }
    46424465
     
    47004523typedef QHash<const QGLContext*, QGLFontGlyphHash*> QGLContextHash;
    47014524
     4525static inline void qt_delete_glyph_hash(QGLGlyphHash *hash)
     4526{
     4527    qDeleteAll(*hash);
     4528    delete hash;
     4529}
     4530
    47024531class QGLGlyphCache : public QObject
    47034532{
     
    47404569            ctx = keys.at(i);
    47414570            QGLGlyphHash *cache = font_cache->take(fe);
    4742             delete cache;
     4571            qt_delete_glyph_hash(cache);
    47434572            break;
    47444573        }
     
    47774606        for (int i=0; i < keys.size(); ++i) {
    47784607            QFontEngine *fe = keys.at(i);
    4779             delete font_cache->take(fe);
     4608            qt_delete_glyph_hash(font_cache->take(fe));
    47804609            quint64 font_key = (reinterpret_cast<quint64>(ctx) << 32) | reinterpret_cast<quint64>(fe);
    47814610            QGLFontTexture *font_tex = qt_font_textures.take(font_key);
     
    48184647    for (int i=0; i < keys.size(); ++i) {
    48194648        QGLFontGlyphHash *font_cache = qt_context_cache.value(keys.at(i));
    4820         qDeleteAll(*font_cache);
     4649        QGLFontGlyphHash::Iterator it = font_cache->begin();
     4650        for (; it != font_cache->end(); ++it)
     4651            qt_delete_glyph_hash(it.value());
    48214652        font_cache->clear();
    48224653    }
     
    48694700        for (int i=0; i<contexts.size(); ++i) {
    48704701            const QGLContext *ctx = contexts.at(i);
    4871             if (ctx != context && qgl_share_reg()->checkSharing(context, ctx)) {
     4702            if (ctx != context && QGLContext::areSharing(context, ctx)) {
    48724703                context_key = ctx;
    48734704                dev_it = qt_context_cache.constFind(context_key);
     
    48864717            connect(widget, SIGNAL(destroyed(QObject*)), SLOT(widgetDestroyed(QObject*)));
    48874718            connect(QGLSignalProxy::instance(),
    4888                     SIGNAL(aboutToDestroyContext(const QGLContext *)),
    4889                     SLOT(cleanupContext(const QGLContext *)));
     4719                    SIGNAL(aboutToDestroyContext(const QGLContext*)),
     4720                    SLOT(cleanupContext(const QGLContext*)));
    48904721        }
    48914722    } else {
     
    49764807            }
    49774808
    4978             QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8));
     4809            QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i]));
     4810            glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
    49794811            glyph_width = glyph_im.width();
    49804812            Q_ASSERT(glyph_width >= 0);
     
    50634895    // fall back to drawing a polygon if the scale factor is large, or
    50644896    // we use a gradient pen
    5065     if (ti.fontEngine->fontDef.pixelSize >= 64
    5066         || (d->matrix.det() > 1) || (d->pen_brush_style >= Qt::LinearGradientPattern
    5067                                      && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
     4897    if ((d->matrix.det() > 1) || (d->pen_brush_style >= Qt::LinearGradientPattern
     4898                                  && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
    50684899        QPaintEngine::drawTextItem(p, textItem);
    50694900        return;
     
    50754906    QVarLengthArray<QFixedPoint> positions;
    50764907    QVarLengthArray<glyph_t> glyphs;
    5077     QTransform matrix;
    5078     matrix.translate(qRound(p.x()), qRound(p.y()));
     4908    QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y()));
    50794909    ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
    50804910
    50814911    // make sure the glyphs we want to draw are in the cache
    5082     qt_glyph_cache()->cacheGlyphs(d->drawable.context(), ti, glyphs);
     4912    qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs);
    50834913
    50844914    d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
     
    51584988            glLoadIdentity();
    51594989
    5160             GLuint program = qt_gl_program_cache()->getProgram(d->drawable.context(),
     4990            GLuint program = qt_gl_program_cache()->getProgram(d->device->context(),
    51614991                                                               FRAGMENT_PROGRAM_MASK_ELLIPSE_AA, 0, true);
    51624992            QGLEllipseMaskGenerator maskGenerator(rect,
     
    52935123
    52945124    int left = qMax(0, static_cast<int>(screen_rect.left()));
    5295     int width = qMin(drawable.size().width() - left, static_cast<int>(screen_rect.width()) + 1);
    5296 
    5297     int bottom = qMax(0, static_cast<int>(drawable.size().height() - screen_rect.bottom()));
    5298     int height = qMin(drawable.size().height() - bottom, static_cast<int>(screen_rect.height()) + 1);
     5125    int width = qMin(device->size().width() - left, static_cast<int>(screen_rect.width()) + 1);
     5126
     5127    int bottom = qMax(0, static_cast<int>(device->size().height() - screen_rect.bottom()));
     5128    int height = qMin(device->size().height() - bottom, static_cast<int>(screen_rect.height()) + 1);
    52995129
    53005130    glBindTexture(GL_TEXTURE_2D, drawable_texture);
     
    53905220
    53915221        if (current_style == Qt::TexturePattern)
    5392             drawable.bindTexture(cbrush.textureImage());
     5222            device->context()->d_func()->bindTexture(cbrush.textureImage(), GL_TEXTURE_2D, GL_RGBA,
     5223                                                     QGLContext::InternalBindOption);
    53935224        else
    5394             drawable.bindTexture(qt_imageForBrush(current_style, true));
     5225            device->context()->d_func()->bindTexture(qt_imageForBrush(current_style, false),
     5226                                                     GL_TEXTURE_2D, GL_RGBA,
     5227                                                     QGLContext::InternalBindOption);
    53955228
    53965229        updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform);
     
    54005233    glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    54015234    glEnable(GL_FRAGMENT_PROGRAM_ARB);
    5402     GLuint program = qt_gl_program_cache()->getProgram(drawable.context(),
     5235    GLuint program = qt_gl_program_cache()->getProgram(device->context(),
    54035236                                                       fragment_brush,
    54045237                                                       fragment_composition_mode, false);
     
    54725305
    54735306    composite(item.location.screen_rect, item.location.rect.topLeft() - item.location.screen_rect.topLeft()
    5474                                          - QPoint(0, offscreen.offscreenSize().height() - drawable.size().height()));
     5307                                         - QPoint(0, offscreen.offscreenSize().height() - device->size().height()));
    54755308}
    54765309
     
    56215454        QBrush oldBrush = p->brush();
    56225455        p->setBrush(brush);
    5623         qt_draw_helper(p->d_ptr, painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
     5456        qt_draw_helper(p->d_ptr.data(), painterPathFromVectorPath(path), QPainterPrivate::FillDraw);
    56245457        p->setBrush(oldBrush);
    56255458        return;
     
    57105543{
    57115544    Q_D(QOpenGLPaintEngine);
     5545    QOpenGLPaintEngineState *new_state = static_cast<QOpenGLPaintEngineState *>(s);
     5546    QOpenGLPaintEngineState *old_state = state();
     5547
    57125548    QPaintEngineEx::setState(s);
     5549
     5550    // are we in a save() ?
     5551    if (s == d->last_created_state) {
     5552        d->last_created_state = 0;
     5553        return;
     5554    }
     5555
    57135556    if (isActive()) {
    5714         d->updateDepthClip();
     5557        if (old_state->depthClipId != new_state->depthClipId)
     5558            d->updateDepthClip();
    57155559        penChanged();
    57165560        brushChanged();
     
    57245568QPainterState *QOpenGLPaintEngine::createState(QPainterState *orig) const
    57255569{
     5570    const Q_D(QOpenGLPaintEngine);
     5571
    57265572    QOpenGLPaintEngineState *s;
    57275573    if (!orig)
     
    57305576        s = new QOpenGLPaintEngineState(*static_cast<QOpenGLPaintEngineState *>(orig));
    57315577
     5578    d->last_created_state = s;
    57325579    return s;
    57335580}
     
    57435590    hasClipping = other.hasClipping;
    57445591    fastClip = other.fastClip;
     5592    depthClipId = other.depthClipId;
    57455593}
    57465594
     
    57485596{
    57495597    hasClipping = false;
     5598    depthClipId = 0;
    57505599}
    57515600
     
    57775626}
    57785627
    5779 QPixmapFilter *QOpenGLPaintEngine::createPixmapFilter(int type) const
    5780 {
    5781     if (QGLContext::currentContext())
    5782         return QGLContext::currentContext()->d_func()->createPixmapFilter(type);
    5783     else
    5784         return 0;
    5785 }
    5786 
    5787 
    57885628QT_END_NAMESPACE
    57895629
  • trunk/src/opengl/qpaintengine_opengl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5959
    6060class QOpenGLPaintEnginePrivate;
     61class QGLTexture;
    6162
    6263class QOpenGLPaintEngineState : public QPainterState
     
    7071    bool hasClipping;
    7172    QRect fastClip;
     73    uint depthClipId;
    7274};
    7375
     
    135137    void drawEllipse(const QRectF &rect);
    136138
    137     QPixmapFilter *createPixmapFilter(int type) const;
    138 
    139139#ifdef Q_WS_WIN
    140140    HDC handle() const;
     
    146146private:
    147147    void drawPolyInternal(const QPolygonF &pa, bool close = true);
    148     void drawTextureRect(int tx_width, int tx_height, const QRectF &r, const QRectF &sr, GLenum target);
     148    void drawTextureRect(int tx_width, int tx_height, const QRectF &r, const QRectF &sr,
     149                         GLenum target, QGLTexture *tex);
    149150    Q_DISABLE_COPY(QOpenGLPaintEngine)
    150151};
  • trunk/src/opengl/qpixmapdata_gl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4141
    4242#include "qpixmap.h"
     43#include "qglframebufferobject.h"
    4344
    4445#include <private/qpaintengine_raster_p.h>
     
    4849#include <private/qgl_p.h>
    4950#include <private/qdrawhelper_p.h>
     51#include <private/qimage_p.h>
     52
     53#include <private/qpaintengineex_opengl2_p.h>
     54
     55#include <qdesktopwidget.h>
     56#include <qfile.h>
     57#include <qimagereader.h>
    5058
    5159QT_BEGIN_NAMESPACE
     
    5361extern QGLWidget* qt_gl_share_widget();
    5462
    55 class QGLShareContextScope
    56 {
    57 public:
    58     QGLShareContextScope(const QGLContext *ctx)
    59         : m_oldContext(0)
    60         , m_ctx(const_cast<QGLContext *>(ctx))
    61     {
    62         const QGLContext *currentContext = QGLContext::currentContext();
    63         if (currentContext != ctx && !qgl_share_reg()->checkSharing(ctx, currentContext)) {
    64             m_oldContext = const_cast<QGLContext *>(currentContext);
    65             m_ctx->makeCurrent();
    66         }
    67     }
    68 
    69     operator QGLContext *()
    70     {
    71         return m_ctx;
    72     }
    73 
    74     QGLContext *operator->()
    75     {
    76         return m_ctx;
    77     }
    78 
    79     ~QGLShareContextScope()
    80     {
    81         if (m_oldContext)
    82             m_oldContext->makeCurrent();
    83     }
    84 
    85 private:
    86     QGLContext *m_oldContext;
    87     QGLContext *m_ctx;
    88 };
    89 
    90 void qt_gl_convertFromGLImage(QImage *img)
    91 {
    92     const int w = img->width();
    93     const int h = img->height();
    94 
    95     if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
    96         uint *p = (uint*)img->bits();
    97         uint *end = p + w*h;
    98 
    99         while (p < end) {
    100             uint a = *p << 24;
    101             *p = (*p >> 8) | a;
    102             p++;
    103         }
    104 
    105         *img = img->mirrored();
    106     } else {
    107         // mirror image
    108         uint *data = (uint *)img->bits();
    109 
    110         const int mid = h/2;
    111 
    112         for (int y = 0; y < mid; ++y) {
    113             uint *p = data + y * w;
    114             uint *end = p + w;
    115             uint *q = data + (h - y - 1) * w;
    116 
    117             while (p < end)
    118                 qSwap(*p++, *q++);
    119         }
    120     }
    121 }
    122 
     63/*!
     64    \class QGLFramebufferObjectPool
     65    \since 4.6
     66
     67    \brief The QGLFramebufferObject class provides a pool of framebuffer
     68    objects for offscreen rendering purposes.
     69
     70    When requesting an FBO of a given size and format, an FBO of the same
     71    format and a size at least as big as the requested size will be returned.
     72
     73    \internal
     74*/
     75
     76static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo)
     77{
     78    return qAbs(size.width() * size.height() - fbo->width() * fbo->height());
     79}
     80
     81extern int qt_next_power_of_two(int v);
     82
     83static inline QSize maybeRoundToNextPowerOfTwo(const QSize &sz)
     84{
     85#ifdef QT_OPENGL_ES_2
     86    QSize rounded(qt_next_power_of_two(sz.width()), qt_next_power_of_two(sz.height()));
     87    if (rounded.width() * rounded.height() < 1.20 * sz.width() * sz.height())
     88        return rounded;
     89#endif
     90    return sz;
     91}
     92
     93
     94QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat, bool strictSize)
     95{
     96    QGLFramebufferObject *chosen = 0;
     97    QGLFramebufferObject *candidate = 0;
     98    for (int i = 0; !chosen && i < m_fbos.size(); ++i) {
     99        QGLFramebufferObject *fbo = m_fbos.at(i);
     100
     101        if (strictSize) {
     102            if (fbo->size() == requestSize && fbo->format() == requestFormat) {
     103                chosen = fbo;
     104                break;
     105            } else {
     106                continue;
     107            }
     108        }
     109
     110        if (fbo->format() == requestFormat) {
     111            // choose the fbo with a matching format and the closest size
     112            if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo))
     113                candidate = fbo;
     114        }
     115
     116        if (candidate) {
     117            m_fbos.removeOne(candidate);
     118
     119            const QSize fboSize = candidate->size();
     120            QSize sz = fboSize;
     121
     122            if (sz.width() < requestSize.width())
     123                sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5)));
     124            if (sz.height() < requestSize.height())
     125                sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5)));
     126
     127            // wasting too much space?
     128            if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 4)
     129                sz = requestSize;
     130
     131            if (sz != fboSize) {
     132                delete candidate;
     133                candidate = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(sz), requestFormat);
     134            }
     135
     136            chosen = candidate;
     137        }
     138    }
     139
     140    if (!chosen) {
     141        if (strictSize)
     142            chosen = new QGLFramebufferObject(requestSize, requestFormat);
     143        else
     144            chosen = new QGLFramebufferObject(maybeRoundToNextPowerOfTwo(requestSize), requestFormat);
     145    }
     146
     147    if (!chosen->isValid()) {
     148        delete chosen;
     149        chosen = 0;
     150    }
     151
     152    return chosen;
     153}
     154
     155void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo)
     156{
     157    if (fbo)
     158        m_fbos << fbo;
     159}
     160
     161
     162QPaintEngine* QGLPixmapGLPaintDevice::paintEngine() const
     163{
     164    return data->paintEngine();
     165}
     166
     167void QGLPixmapGLPaintDevice::beginPaint()
     168{
     169    if (!data->isValid())
     170        return;
     171
     172    // QGLPaintDevice::beginPaint will store the current binding and replace
     173    // it with m_thisFBO:
     174    m_thisFBO = data->m_renderFbo->handle();
     175    QGLPaintDevice::beginPaint();
     176
     177    Q_ASSERT(data->paintEngine()->type() == QPaintEngine::OpenGL2);
     178
     179    // QPixmap::fill() is deferred until now, where we actually need to do the fill:
     180    if (data->needsFill()) {
     181        const QColor &c = data->fillColor();
     182        float alpha = c.alphaF();
     183        glDisable(GL_SCISSOR_TEST);
     184        glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
     185        glClear(GL_COLOR_BUFFER_BIT);
     186    }
     187    else if (!data->isUninitialized()) {
     188        // If the pixmap (GL Texture) has valid content (it has been
     189        // uploaded from an image or rendered into before), we need to
     190        // copy it from the texture to the render FBO.
     191
     192        glDisable(GL_DEPTH_TEST);
     193        glDisable(GL_SCISSOR_TEST);
     194        glDisable(GL_BLEND);
     195
     196#if !defined(QT_OPENGL_ES_2)
     197        glMatrixMode(GL_MODELVIEW);
     198        glLoadIdentity();
     199
     200        glMatrixMode(GL_PROJECTION);
     201        glLoadIdentity();
     202        glOrtho(0, data->width(), data->height(), 0, -999999, 999999);
     203#endif
     204
     205        glViewport(0, 0, data->width(), data->height());
     206
     207        // Pass false to bind so it doesn't copy the FBO into the texture!
     208        context()->drawTexture(QRect(0, 0, data->width(), data->height()), data->bind(false));
     209    }
     210}
     211
     212void QGLPixmapGLPaintDevice::endPaint()
     213{
     214    if (!data->isValid())
     215        return;
     216
     217    data->copyBackFromRenderFbo(false);
     218
     219    // Base's endPaint will restore the previous FBO binding
     220    QGLPaintDevice::endPaint();
     221
     222    qgl_fbo_pool()->release(data->m_renderFbo);
     223    data->m_renderFbo = 0;
     224}
     225
     226QGLContext* QGLPixmapGLPaintDevice::context() const
     227{
     228    data->ensureCreated();
     229    return data->m_ctx;
     230}
     231
     232QSize QGLPixmapGLPaintDevice::size() const
     233{
     234    return data->size();
     235}
     236
     237void QGLPixmapGLPaintDevice::setPixmapData(QGLPixmapData* d)
     238{
     239    data = d;
     240}
    123241
    124242static int qt_gl_pixmap_serial = 0;
     
    126244QGLPixmapData::QGLPixmapData(PixelType type)
    127245    : QPixmapData(type, OpenGLClass)
    128     , m_width(0)
    129     , m_height(0)
    130     , m_texture(0)
     246    , m_renderFbo(0)
     247    , m_engine(0)
     248    , m_ctx(0)
    131249    , m_dirty(false)
     250    , m_hasFillColor(false)
     251    , m_hasAlpha(false)
    132252{
    133253    setSerialNumber(++qt_gl_pixmap_serial);
     254    m_glDevice.setPixmapData(this);
    134255}
    135256
    136257QGLPixmapData::~QGLPixmapData()
    137258{
    138     if (m_texture && qt_gl_share_widget()) {
     259    QGLWidget *shareWidget = qt_gl_share_widget();
     260    if (!shareWidget)
     261        return;
     262
     263    delete m_engine;
     264
     265    if (m_texture.id) {
     266        QGLShareContextScope ctx(shareWidget->context());
     267        glDeleteTextures(1, &m_texture.id);
     268    }
     269}
     270
     271QPixmapData *QGLPixmapData::createCompatiblePixmapData() const
     272{
     273    return new QGLPixmapData(pixelType());
     274}
     275
     276bool QGLPixmapData::isValid() const
     277{
     278    return w > 0 && h > 0;
     279}
     280
     281bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
     282{
     283    if (ctx == m_ctx)
     284        return true;
     285
     286    const QGLContext *share_ctx = qt_gl_share_widget()->context();
     287    return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx);
     288}
     289
     290void QGLPixmapData::resize(int width, int height)
     291{
     292    if (width == w && height == h)
     293        return;
     294
     295    if (width <= 0 || height <= 0) {
     296        width = 0;
     297        height = 0;
     298    }
     299
     300    w = width;
     301    h = height;
     302    is_null = (w <= 0 || h <= 0);
     303    d = pixelType() == QPixmapData::PixmapType ? 32 : 1;
     304
     305    if (m_texture.id) {
    139306        QGLShareContextScope ctx(qt_gl_share_widget()->context());
    140         glDeleteTextures(1, &m_texture);
    141     }
    142 }
    143 
    144 bool QGLPixmapData::isValid() const
    145 {
    146     return m_width > 0 && m_height > 0;
    147 }
    148 
    149 bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
    150 {
    151     const QGLContext *share_ctx = qt_gl_share_widget()->context();
    152     return ctx == share_ctx || qgl_share_reg()->checkSharing(ctx, share_ctx);
    153 }
    154 
    155 void QGLPixmapData::resize(int width, int height)
    156 {
    157     if (width == m_width && height == m_height)
    158         return;
    159 
    160     m_width = width;
    161     m_height = height;
     307        glDeleteTextures(1, &m_texture.id);
     308        m_texture.id = 0;
     309    }
    162310
    163311    m_source = QImage();
     
    174322
    175323    QGLShareContextScope ctx(qt_gl_share_widget()->context());
    176 
    177     const GLenum format = qt_gl_preferredTextureFormat();
    178     const GLenum target = qt_gl_preferredTextureTarget();
    179 
    180     if (!m_texture)
    181         glGenTextures(1, &m_texture);
    182 
    183     glBindTexture(target, m_texture);
    184 
    185     if (m_source.isNull()) {
    186         glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format, GL_UNSIGNED_BYTE, 0);
    187     } else {
    188         const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format);
    189 
    190         glBindTexture(target, m_texture);
    191         glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format,
    192                 GL_UNSIGNED_BYTE, tx.bits());
    193 
    194         m_source = QImage();
    195     }
     324    m_ctx = ctx;
     325
     326    const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB;
     327#ifdef QT_OPENGL_ES_2
     328    const GLenum external_format = internal_format;
     329#else
     330    const GLenum external_format = qt_gl_preferredTextureFormat();
     331#endif
     332    const GLenum target = GL_TEXTURE_2D;
     333
     334    if (!m_texture.id) {
     335        glGenTextures(1, &m_texture.id);
     336        glBindTexture(target, m_texture.id);
     337        glTexImage2D(target, 0, internal_format, w, h, 0, external_format, GL_UNSIGNED_BYTE, 0);
     338        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     339        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     340    }
     341
     342    if (!m_source.isNull()) {
     343        if (external_format == GL_RGB) {
     344            const QImage tx = m_source.convertToFormat(QImage::Format_RGB888);
     345
     346            glBindTexture(target, m_texture.id);
     347            glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
     348                            GL_UNSIGNED_BYTE, tx.bits());
     349        } else {
     350            const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, external_format);
     351
     352            glBindTexture(target, m_texture.id);
     353            glTexSubImage2D(target, 0, 0, 0, w, h, external_format,
     354                            GL_UNSIGNED_BYTE, tx.bits());
     355        }
     356
     357        if (useFramebufferObjects())
     358            m_source = QImage();
     359    }
     360
     361    m_texture.options &= ~QGLContext::MemoryManagedBindOption;
    196362}
    197363
    198364void QGLPixmapData::fromImage(const QImage &image,
    199                               Qt::ImageConversionFlags)
    200 {
    201     if (image.size() == QSize(m_width, m_height))
     365                              Qt::ImageConversionFlags /*flags*/)
     366{
     367    if (image.size() == QSize(w, h))
    202368        setSerialNumber(++qt_gl_pixmap_serial);
    203369    resize(image.width(), image.height());
    204     m_source = image;
     370
     371    if (pixelType() == BitmapType) {
     372        m_source = image.convertToFormat(QImage::Format_MonoLSB);
     373
     374    } else {
     375        QImage::Format format = QImage::Format_RGB32;
     376        if (qApp->desktop()->depth() == 16)
     377            format = QImage::Format_RGB16;
     378
     379        if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())
     380            format = QImage::Format_ARGB32_Premultiplied;;
     381
     382        m_source = image.convertToFormat(format);
     383    }
     384
    205385    m_dirty = true;
     386    m_hasFillColor = false;
     387
     388    m_hasAlpha = m_source.hasAlphaChannel();
     389    w = image.width();
     390    h = image.height();
     391    is_null = (w <= 0 || h <= 0);
     392    d = m_source.depth();
     393
     394    if (m_texture.id) {
     395        QGLShareContextScope ctx(qt_gl_share_widget()->context());
     396        glDeleteTextures(1, &m_texture.id);
     397        m_texture.id = 0;
     398    }
     399}
     400
     401bool QGLPixmapData::fromFile(const QString &filename, const char *format,
     402                             Qt::ImageConversionFlags flags)
     403{
     404    if (pixelType() == QPixmapData::BitmapType)
     405        return QPixmapData::fromFile(filename, format, flags);
     406    QFile file(filename);
     407    if (!file.open(QIODevice::ReadOnly))
     408        return false;
     409    QByteArray data = file.peek(64);
     410    bool alpha;
     411    if (m_texture.canBindCompressedTexture
     412            (data.constData(), data.size(), format, &alpha)) {
     413        resize(0, 0);
     414        data = file.readAll();
     415        file.close();
     416        QGLShareContextScope ctx(qt_gl_share_widget()->context());
     417        QSize size = m_texture.bindCompressedTexture
     418            (data.constData(), data.size(), format);
     419        if (!size.isEmpty()) {
     420            w = size.width();
     421            h = size.height();
     422            is_null = false;
     423            d = 32;
     424            m_hasAlpha = alpha;
     425            m_source = QImage();
     426            m_dirty = isValid();
     427            return true;
     428        }
     429        return false;
     430    }
     431    fromImage(QImageReader(&file, format).read(), flags);
     432    return !isNull();
     433}
     434
     435bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format,
     436                             Qt::ImageConversionFlags flags)
     437{
     438    bool alpha;
     439    const char *buf = reinterpret_cast<const char *>(buffer);
     440    if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) {
     441        resize(0, 0);
     442        QGLShareContextScope ctx(qt_gl_share_widget()->context());
     443        QSize size = m_texture.bindCompressedTexture(buf, int(len), format);
     444        if (!size.isEmpty()) {
     445            w = size.width();
     446            h = size.height();
     447            is_null = false;
     448            d = 32;
     449            m_hasAlpha = alpha;
     450            m_source = QImage();
     451            m_dirty = isValid();
     452            return true;
     453        }
     454    }
     455    return QPixmapData::fromData(buffer, len, format, flags);
     456}
     457
     458bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
     459{
     460    Q_UNUSED(dx);
     461    Q_UNUSED(dy);
     462    Q_UNUSED(rect);
     463    return false;
     464}
     465
     466void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
     467{
     468    if (data->classId() != QPixmapData::OpenGLClass) {
     469        QPixmapData::copy(data, rect);
     470        return;
     471    }
     472
     473    // can be optimized to do a framebuffer blit or similar ...
     474    QPixmapData::copy(data, rect);
    206475}
    207476
     
    211480        return;
    212481
    213     if (!m_source.isNull()) {
    214         m_source.fill(PREMUL(color.rgba()));
     482    bool hasAlpha = color.alpha() != 255;
     483    if (hasAlpha && !m_hasAlpha) {
     484        if (m_texture.id) {
     485            glDeleteTextures(1, &m_texture.id);
     486            m_texture.id = 0;
     487            m_dirty = true;
     488        }
     489        m_hasAlpha = color.alpha() != 255;
     490    }
     491
     492    if (useFramebufferObjects()) {
     493        m_source = QImage();
     494        m_hasFillColor = true;
     495        m_fillColor = color;
    215496    } else {
    216         // ## TODO: improve performance here
    217         QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
     497
     498        if (m_source.isNull()) {
     499            m_fillColor = color;
     500            m_hasFillColor = true;
     501
     502        } else if (m_source.depth() == 32) {
     503            m_source.fill(PREMUL(color.rgba()));
     504
     505        } else if (m_source.depth() == 1) {
     506            if (color == Qt::color1)
     507                m_source.fill(1);
     508            else
     509                m_source.fill(0);
     510        }
     511    }
     512}
     513
     514bool QGLPixmapData::hasAlphaChannel() const
     515{
     516    return m_hasAlpha;
     517}
     518
     519QImage QGLPixmapData::fillImage(const QColor &color) const
     520{
     521    QImage img;
     522    if (pixelType() == BitmapType) {
     523        img = QImage(w, h, QImage::Format_MonoLSB);
     524
     525        img.setColorCount(2);
     526        img.setColor(0, QColor(Qt::color0).rgba());
     527        img.setColor(1, QColor(Qt::color1).rgba());
     528
     529        if (color == Qt::color1)
     530            img.fill(1);
     531        else
     532            img.fill(0);
     533    } else {
     534        img = QImage(w, h,
     535                m_hasAlpha
     536                ? QImage::Format_ARGB32_Premultiplied
     537                : QImage::Format_RGB32);
    218538        img.fill(PREMUL(color.rgba()));
    219 
    220         fromImage(img, 0);
    221     }
    222 }
    223 
    224 bool QGLPixmapData::hasAlphaChannel() const
    225 {
    226     return true;
    227 }
     539    }
     540    return img;
     541}
     542
     543extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha);
    228544
    229545QImage QGLPixmapData::toImage() const
     
    232548        return QImage();
    233549
    234     if (!m_source.isNull())
     550    if (m_renderFbo) {
     551        copyBackFromRenderFbo(true);
     552    } else if (!m_source.isNull()) {
    235553        return m_source;
    236     else if (m_dirty)
    237         return QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
     554    } else if (m_dirty || m_hasFillColor) {
     555        return fillImage(m_fillColor);
     556    } else {
     557        ensureCreated();
     558    }
     559
     560    QGLShareContextScope ctx(qt_gl_share_widget()->context());
     561    glBindTexture(GL_TEXTURE_2D, m_texture.id);
     562    return qt_gl_read_texture(QSize(w, h), true, true);
     563}
     564
     565struct TextureBuffer
     566{
     567    QGLFramebufferObject *fbo;
     568    QGL2PaintEngineEx *engine;
     569};
     570
     571Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool)
     572QGLFramebufferObjectPool* qgl_fbo_pool()
     573{
     574    return _qgl_fbo_pool();
     575}
     576
     577void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
     578{
     579    if (!isValid())
     580        return;
     581
     582    m_hasFillColor = false;
     583
     584    const QGLContext *share_ctx = qt_gl_share_widget()->context();
     585    QGLShareContextScope ctx(share_ctx);
    238586
    239587    ensureCreated();
    240588
    241     QGLShareContextScope ctx(qt_gl_share_widget()->context());
    242     QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
    243 
    244     GLenum format = qt_gl_preferredTextureFormat();
    245     GLenum target = qt_gl_preferredTextureTarget();
    246 
    247     glBindTexture(target, m_texture);
    248 #ifndef QT_OPENGL_ES
    249     glGetTexImage(target, 0, format, GL_UNSIGNED_BYTE, img.bits());
    250 #else
    251     // XXX - cannot download textures this way on OpenGL/ES.
    252 #endif
    253 
    254     qt_gl_convertFromGLImage(&img);
    255 
    256     return img;
     589    if (!ctx->d_ptr->fbo)
     590        glGenFramebuffers(1, &ctx->d_ptr->fbo);
     591
     592    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
     593    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
     594        GL_TEXTURE_2D, m_texture.id, 0);
     595
     596    const int x0 = 0;
     597    const int x1 = w;
     598    const int y0 = 0;
     599    const int y1 = h;
     600
     601    if (!m_renderFbo->isBound())
     602        glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
     603
     604    glDisable(GL_SCISSOR_TEST);
     605
     606    glBlitFramebufferEXT(x0, y0, x1, y1,
     607            x0, y0, x1, y1,
     608            GL_COLOR_BUFFER_BIT,
     609            GL_NEAREST);
     610
     611    if (keepCurrentFboBound) {
     612        glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
     613    } else {
     614        glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_renderFbo->handle());
     615        ctx->d_ptr->current_fbo = m_renderFbo->handle();
     616    }
     617}
     618
     619bool QGLPixmapData::useFramebufferObjects()
     620{
     621    return QGLFramebufferObject::hasOpenGLFramebufferObjects()
     622           && QGLFramebufferObject::hasOpenGLFramebufferBlit()
     623           && qt_gl_preferGL2Engine();
    257624}
    258625
     
    262629        return 0;
    263630
    264     m_source = toImage();
     631    if (m_renderFbo)
     632        return m_engine;
     633
     634    if (useFramebufferObjects()) {
     635        extern QGLWidget* qt_gl_share_widget();
     636
     637        if (!QGLContext::currentContext())
     638            qt_gl_share_widget()->makeCurrent();
     639        QGLShareContextScope ctx(qt_gl_share_widget()->context());
     640
     641        QGLFramebufferObjectFormat format;
     642        format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
     643        format.setSamples(4);
     644        format.setInternalTextureFormat(GLenum(m_hasAlpha ? GL_RGBA : GL_RGB));
     645
     646        m_renderFbo = qgl_fbo_pool()->acquire(size(), format);
     647
     648        if (m_renderFbo) {
     649            if (!m_engine)
     650                m_engine = new QGL2PaintEngineEx;
     651            return m_engine;
     652        }
     653
     654        qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
     655    }
     656
    265657    m_dirty = true;
    266 
     658    if (m_source.size() != size())
     659        m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied);
     660    if (m_hasFillColor) {
     661        m_source.fill(PREMUL(m_fillColor.rgba()));
     662        m_hasFillColor = false;
     663    }
    267664    return m_source.paintEngine();
    268665}
    269666
    270 GLuint QGLPixmapData::bind() const
    271 {
    272     ensureCreated();
    273     glBindTexture(qt_gl_preferredTextureTarget(), m_texture);
    274     return m_texture;
    275 }
    276 
    277 GLuint QGLPixmapData::textureId() const
    278 {
    279     ensureCreated();
    280     return m_texture;
     667extern QRgb qt_gl_convertToGLFormat(QRgb src_pixel, GLenum texture_format);
     668
     669// If copyBack is true, bind will copy the contents of the render
     670// FBO to the texture (which is not bound to the texture, as it's
     671// a multisample FBO).
     672GLuint QGLPixmapData::bind(bool copyBack) const
     673{
     674    if (m_renderFbo && copyBack) {
     675        copyBackFromRenderFbo(true);
     676    } else {
     677        ensureCreated();
     678    }
     679
     680    GLuint id = m_texture.id;
     681    glBindTexture(GL_TEXTURE_2D, id);
     682
     683    if (m_hasFillColor) {
     684        if (!useFramebufferObjects()) {
     685            m_source = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
     686            m_source.fill(PREMUL(m_fillColor.rgba()));
     687        }
     688
     689        m_hasFillColor = false;
     690
     691        GLenum format = qt_gl_preferredTextureFormat();
     692        QImage tx(w, h, QImage::Format_ARGB32_Premultiplied);
     693        tx.fill(qt_gl_convertToGLFormat(m_fillColor.rgba(), format));
     694        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits());
     695    }
     696
     697    return id;
     698}
     699
     700QGLTexture* QGLPixmapData::texture() const
     701{
     702    return &m_texture;
    281703}
    282704
     
    286708int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
    287709{
     710    if (w == 0)
     711        return 0;
     712
    288713    switch (metric) {
    289714    case QPaintDevice::PdmWidth:
    290         return m_width;
     715        return w;
    291716    case QPaintDevice::PdmHeight:
    292         return m_height;
     717        return h;
    293718    case QPaintDevice::PdmNumColors:
    294719        return 0;
    295720    case QPaintDevice::PdmDepth:
    296         return pixelType() == QPixmapData::PixmapType ? 32 : 1;
     721        return d;
    297722    case QPaintDevice::PdmWidthMM:
    298         return qRound(m_width * 25.4 / qt_defaultDpiX());
     723        return qRound(w * 25.4 / qt_defaultDpiX());
    299724    case QPaintDevice::PdmHeightMM:
    300         return qRound(m_height * 25.4 / qt_defaultDpiY());
     725        return qRound(h * 25.4 / qt_defaultDpiY());
    301726    case QPaintDevice::PdmDpiX:
    302727    case QPaintDevice::PdmPhysicalDpiX:
     
    311736}
    312737
     738QGLPaintDevice *QGLPixmapData::glDevice() const
     739{
     740    return &m_glDevice;
     741}
     742
    313743QT_END_NAMESPACE
  • trunk/src/opengl/qpixmapdata_gl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5454//
    5555
     56#include "qgl_p.h"
    5657#include "qgl.h"
    5758
    5859#include "private/qpixmapdata_p.h"
     60#include "private/qglpaintdevice_p.h"
    5961
    6062QT_BEGIN_NAMESPACE
    6163
    6264class QPaintEngine;
     65class QGLFramebufferObject;
     66class QGLFramebufferObjectFormat;
     67class QGLPixmapData;
     68
     69class QGLFramebufferObjectPool
     70{
     71public:
     72    QGLFramebufferObject *acquire(const QSize &size, const QGLFramebufferObjectFormat &format, bool strictSize = false);
     73    void release(QGLFramebufferObject *fbo);
     74
     75private:
     76    QList<QGLFramebufferObject *> m_fbos;
     77};
     78
     79QGLFramebufferObjectPool* qgl_fbo_pool();
     80
     81
     82class QGLPixmapGLPaintDevice : public QGLPaintDevice
     83{
     84public:
     85    QPaintEngine* paintEngine() const;
     86
     87    void beginPaint();
     88    void endPaint();
     89    QGLContext* context() const;
     90    QSize size() const;
     91
     92    void setPixmapData(QGLPixmapData*);
     93private:
     94    QGLPixmapData *data;
     95};
     96
    6397
    6498class QGLPixmapData : public QPixmapData
     
    68102    ~QGLPixmapData();
    69103
    70     bool isValid() const;
     104    QPixmapData *createCompatiblePixmapData() const;
    71105
     106    // Re-implemented from QPixmapData:
    72107    void resize(int width, int height);
    73     void fromImage(const QImage &image,
    74                    Qt::ImageConversionFlags flags);
    75 
     108    void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
     109    bool fromFile(const QString &filename, const char *format,
     110                  Qt::ImageConversionFlags flags);
     111    bool fromData(const uchar *buffer, uint len, const char *format,
     112                  Qt::ImageConversionFlags flags);
     113    void copy(const QPixmapData *data, const QRect &rect);
     114    bool scroll(int dx, int dy, const QRect &rect);
    76115    void fill(const QColor &color);
    77116    bool hasAlphaChannel() const;
    78117    QImage toImage() const;
    79     QPaintEngine* paintEngine() const;
     118    QPaintEngine *paintEngine() const;
     119    int metric(QPaintDevice::PaintDeviceMetric metric) const;
    80120
    81     GLuint bind() const;
    82     GLuint textureId() const;
     121    // For accessing as a target:
     122    QGLPaintDevice *glDevice() const;
    83123
     124    // For accessing as a source:
    84125    bool isValidContext(const QGLContext *ctx) const;
     126    GLuint bind(bool copyBack = true) const;
     127    QGLTexture *texture() const;
     128
     129private:
     130    bool isValid() const;
    85131
    86132    void ensureCreated() const;
    87133
    88 protected:
    89     int metric(QPaintDevice::PaintDeviceMetric metric) const;
     134    bool isUninitialized() const { return m_dirty && m_source.isNull(); }
    90135
    91 private:
     136    bool needsFill() const { return m_hasFillColor; }
     137    QColor fillColor() const { return m_fillColor; }
     138
     139
     140
    92141    QGLPixmapData(const QGLPixmapData &other);
    93142    QGLPixmapData &operator=(const QGLPixmapData &other);
    94143
    95     int m_width;
    96     int m_height;
     144    void copyBackFromRenderFbo(bool keepCurrentFboBound) const;
     145    QSize size() const { return QSize(w, h); }
    97146
    98     mutable GLuint m_texture;
     147    static bool useFramebufferObjects();
     148
     149    QImage fillImage(const QColor &color) const;
     150
     151    mutable QGLFramebufferObject *m_renderFbo;
     152    mutable QPaintEngine *m_engine;
     153    mutable QGLContext *m_ctx;
     154    mutable QImage m_source;
     155    mutable QGLTexture m_texture;
     156
     157    // the texture is not in sync with the source image
    99158    mutable bool m_dirty;
    100     mutable QImage m_source;
     159
     160    // fill has been called and no painting has been done, so the pixmap is
     161    // represented by a single fill color
     162    mutable QColor m_fillColor;
     163    mutable bool m_hasFillColor;
     164
     165    mutable bool m_hasAlpha;
     166
     167    mutable QGLPixmapGLPaintDevice m_glDevice;
     168
     169    friend class QGLPixmapGLPaintDevice;
    101170};
    102171
  • trunk/src/opengl/qwindowsurface_gl.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5050#include <qcolormap.h>
    5151#include <qdesktopwidget.h>
     52#include <private/qwidget_p.h>
    5253#include "qdebug.h"
    5354
     
    5556#include <private/qt_x11_p.h>
    5657#include <qx11info_x11.h>
    57 #include <private/qwidget_p.h>
    5858
    5959#ifndef QT_OPENGL_ES
     
    7070#include <private/qglpixelbuffer_p.h>
    7171#include <private/qgraphicssystem_gl_p.h>
     72
     73#include <private/qpaintengineex_opengl2_p.h>
     74#include <private/qpixmapdata_gl_p.h>
     75
     76#ifndef QT_OPENGL_ES_2
    7277#include <private/qpaintengine_opengl_p.h>
     78#endif
    7379
    7480#ifndef GLX_ARB_multisample
    7581#define GLX_SAMPLE_BUFFERS_ARB  100000
    7682#define GLX_SAMPLES_ARB         100001
     83#endif
     84
     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>
    7791#endif
    7892
     
    8397//
    8498#ifdef Q_WS_WIN
    85 Q_GUI_EXPORT bool qt_win_owndc_required;
     99extern Q_GUI_EXPORT bool qt_win_owndc_required;
    86100#endif
    87101QGLGraphicsSystem::QGLGraphicsSystem()
     
    97111        int spec[16];
    98112        spec[i++] = GLX_RGBA;
    99 #if 0
    100113        spec[i++] = GLX_DOUBLEBUFFER;
    101         spec[i++] = GLX_DEPTH_SIZE;
    102         spec[i++] = 8;
    103         spec[i++] = GLX_STENCIL_SIZE;
    104         spec[i++] = 8;
    105         spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
    106         spec[i++] = 1;
    107         spec[i++] = GLX_SAMPLES_ARB;
    108         spec[i++] = 4;
    109 #endif
     114
     115        if (!qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull()) {
     116            spec[i++] = GLX_DEPTH_SIZE;
     117            spec[i++] = 8;
     118            spec[i++] = GLX_STENCIL_SIZE;
     119            spec[i++] = 8;
     120            spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
     121            spec[i++] = 1;
     122            spec[i++] = GLX_SAMPLES_ARB;
     123            spec[i++] = 4;
     124        }
     125
    110126        spec[i++] = XNone;
    111127
     
    161177    }
    162178#elif defined(Q_WS_WIN)
    163     QGLWindowSurface::surfaceFormat.setDoubleBuffer(false);
     179    QGLWindowSurface::surfaceFormat.setDoubleBuffer(true);
    164180
    165181    qt_win_owndc_required = true;
     
    174190{
    175191public:
    176     QGLGlobalShareWidget() : widget(0) {}
     192    QGLGlobalShareWidget() : widget(0), initializing(false) {}
    177193
    178194    QGLWidget *shareWidget() {
    179         if (!widget && !cleanedUp) {
     195        if (!initializing && !widget && !cleanedUp) {
     196            initializing = true;
    180197            widget = new QGLWidget;
     198            // We dont need this internal widget to appear in QApplication::topLevelWidgets()
     199            if (QWidgetPrivate::allWidgets)
     200                QWidgetPrivate::allWidgets->remove(widget);
     201            initializing = false;
    181202        }
    182203        return widget;
     
    184205
    185206    void cleanup() {
    186         delete widget;
     207        QGLWidget *w = widget;
     208        cleanedUp = true;
    187209        widget = 0;
    188         cleanedUp = true;
     210        delete w;
    189211    }
    190212
     
    193215private:
    194216    QGLWidget *widget;
     217    bool initializing;
    195218};
    196219
     
    215238}
    216239
     240
    217241struct QGLWindowSurfacePrivate
    218242{
     
    224248    int tried_fbo : 1;
    225249    int tried_pb : 1;
     250    int destructive_swap_buffers : 1;
     251    int geometry_updated : 1;
    226252
    227253    QGLContext *ctx;
     
    233259
    234260    QList<QImage> buffers;
     261    QGLWindowSurfaceGLPaintDevice glDevice;
     262    QGLWindowSurface* q_ptr;
    235263};
    236264
    237265QGLFormat QGLWindowSurface::surfaceFormat;
     266
     267void QGLWindowSurfaceGLPaintDevice::endPaint()
     268{
     269    glFlush();
     270    QGLPaintDevice::endPaint();
     271}
     272
     273QSize QGLWindowSurfaceGLPaintDevice::size() const
     274{
     275    return d->size;
     276}
     277
     278QGLContext* QGLWindowSurfaceGLPaintDevice::context() const
     279{
     280    return d->ctx;
     281}
     282
     283
     284int QGLWindowSurfaceGLPaintDevice::metric(PaintDeviceMetric m) const
     285{
     286    return qt_paint_device_metric(d->q_ptr->window(), m);
     287}
     288
     289QPaintEngine *QGLWindowSurfaceGLPaintDevice::paintEngine() const
     290{
     291    return qt_qgl_paint_engine();
     292}
    238293
    239294QGLWindowSurface::QGLWindowSurface(QWidget *window)
     
    245300    d_ptr->fbo = 0;
    246301    d_ptr->ctx = 0;
     302#if defined (QT_OPENGL_ES_2)
     303    d_ptr->tried_fbo = true;
     304    d_ptr->tried_pb = true;
     305#else
    247306    d_ptr->tried_fbo = false;
    248307    d_ptr->tried_pb = false;
     308#endif
     309    d_ptr->destructive_swap_buffers = qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull();
     310    d_ptr->glDevice.d = d_ptr;
     311    d_ptr->q_ptr = this;
     312    d_ptr->geometry_updated = false;
    249313}
    250314
     
    263327}
    264328
     329void QGLWindowSurface::deleted(QObject *object)
     330{
     331    // Make sure that the fbo is destroyed before destroying its context.
     332    delete d_ptr->fbo;
     333    d_ptr->fbo = 0;
     334
     335    QWidget *widget = qobject_cast<QWidget *>(object);
     336    if (widget) {
     337        QWidgetPrivate *widgetPrivate = widget->d_func();
     338        if (widgetPrivate->extraData()) {
     339            union { QGLContext **ctxPtr; void **voidPtr; };
     340            voidPtr = &widgetPrivate->extraData()->glContext;
     341            int index = d_ptr->contexts.indexOf(ctxPtr);
     342            if (index != -1) {
     343                delete *ctxPtr;
     344                *ctxPtr = 0;
     345                d_ptr->contexts.removeAt(index);
     346            }
     347        }
     348    }
     349}
     350
    265351void QGLWindowSurface::hijackWindow(QWidget *widget)
    266352{
     
    272358    QGLContext *ctx = new QGLContext(surfaceFormat, widget);
    273359    ctx->create(qt_gl_share_widget()->context());
    274 #ifdef Q_WS_MAC
    275     ctx->updatePaintDevice();
    276 #endif
     360
     361#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
     362    // Create the EGL surface to draw into.  QGLContext::chooseContext()
     363    // does not do this for X11/EGL, but does do it for other platforms.
     364    // This probably belongs in qgl_x11egl.cpp.
     365    QGLContextPrivate *ctxpriv = ctx->d_func();
     366    ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(widget);
     367    if (ctxpriv->eglSurface == EGL_NO_SURFACE) {
     368        qWarning() << "hijackWindow() could not create EGL surface";
     369    }
     370    qDebug("QGLWindowSurface - using EGLConfig %d", reinterpret_cast<int>(ctxpriv->eglContext->config()));
     371#endif
     372
    277373    widgetPrivate->extraData()->glContext = ctx;
    278374
    279375    union { QGLContext **ctxPtr; void **voidPtr; };
     376
     377    connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(deleted(QObject*)));
    280378
    281379    voidPtr = &widgetPrivate->extraData()->glContext;
     
    284382}
    285383
    286 #if !defined(QT_OPENGL_ES_2)
    287 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_window_surface_paintengine)
    288 #endif
    289 
    290 /*! \reimp */
    291 QPaintEngine *QGLWindowSurface::paintEngine() const
    292 {
    293 #if !defined(QT_OPENGL_ES_2)
    294     return qt_gl_window_surface_paintengine();
    295 #else
    296     return 0;
    297 #endif
    298 }
    299 
    300 int QGLWindowSurface::metric(PaintDeviceMetric m) const
    301 {
    302     return window()->metric(m);
    303 }
    304 
    305384QGLContext *QGLWindowSurface::context() const
    306385{
     
    310389QPaintDevice *QGLWindowSurface::paintDevice()
    311390{
     391    updateGeometry();
     392
    312393    if (d_ptr->pb)
    313394        return d_ptr->pb;
    314395
    315396    if (d_ptr->ctx)
    316         return this;
     397        return &d_ptr->glDevice;
    317398
    318399    QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
     
    337418void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
    338419{
     420    if (context() && widget != window()) {
     421        qWarning("No native child widget support in GL window surface without FBOs or pixel buffers");
     422        return;
     423    }
     424
     425    //### Find out why d_ptr->geometry_updated isn't always false.
     426    // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either
     427    // d_ptr->fbo or d_ptr->pb is allocated and has the correct size.
     428    if (d_ptr->geometry_updated)
     429        return;
     430
    339431    QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
    340432    Q_ASSERT(parent);
    341433
     434    if (!geometry().isValid())
     435        return;
     436
     437    // Needed to support native child-widgets...
    342438    hijackWindow(parent);
    343439
     
    347443    QRect rect = br.translated(-offset - wOffset);
    348444
    349     const GLenum target = qt_gl_preferredTextureTarget();
     445    const GLenum target = GL_TEXTURE_2D;
     446    Q_UNUSED(target);
    350447
    351448    if (context()) {
     
    353450
    354451        if (context()->format().doubleBuffer()) {
    355             glBindTexture(target, d_ptr->tex_id);
    356 
    357             QVector<QRect> rects = d_ptr->paintedRegion.rects();
    358             for (int i = 0; i < rects.size(); ++i) {
    359                 QRect br = rects.at(i);
    360                 if (br.isEmpty())
    361                     continue;
    362 
    363                 const uint bottom = window()->height() - (br.y() + br.height());
    364                 glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
    365             }
    366 
    367             glBindTexture(target, 0);
    368 
    369             QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
    370 
    371             if (!dirtyRegion.isEmpty()) {
    372                 context()->makeCurrent();
    373 
    374                 glMatrixMode(GL_MODELVIEW);
    375                 glLoadIdentity();
    376 
    377                 glMatrixMode(GL_PROJECTION);
    378                 glLoadIdentity();
     452#if !defined(QT_OPENGL_ES_2)
     453            if (d_ptr->destructive_swap_buffers) {
     454                glBindTexture(target, d_ptr->tex_id);
     455
     456                QVector<QRect> rects = d_ptr->paintedRegion.rects();
     457                for (int i = 0; i < rects.size(); ++i) {
     458                    QRect br = rects.at(i);
     459                    if (br.isEmpty())
     460                        continue;
     461
     462                    const uint bottom = window()->height() - (br.y() + br.height());
     463                    glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
     464                }
     465
     466                glBindTexture(target, 0);
     467
     468                QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
     469
     470                if (!dirtyRegion.isEmpty()) {
     471                    glMatrixMode(GL_MODELVIEW);
     472                    glLoadIdentity();
     473
     474                    glMatrixMode(GL_PROJECTION);
     475                    glLoadIdentity();
    379476#ifndef QT_OPENGL_ES
    380                 glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
     477                    glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
    381478#else
    382                 glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
    383 #endif
    384                 glViewport(0, 0, window()->width(), window()->height());
    385 
    386                 QVector<QRect> rects = dirtyRegion.rects();
    387                 glColor4f(1, 1, 1, 1);
    388                 for (int i = 0; i < rects.size(); ++i) {
    389                     QRect rect = rects.at(i);
    390                     if (rect.isEmpty())
    391                         continue;
    392 
    393                     drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
     479                    glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
     480#endif
     481                    glViewport(0, 0, window()->width(), window()->height());
     482
     483                    QVector<QRect> rects = dirtyRegion.rects();
     484                    glColor4f(1, 1, 1, 1);
     485                    for (int i = 0; i < rects.size(); ++i) {
     486                        QRect rect = rects.at(i);
     487                        if (rect.isEmpty())
     488                            continue;
     489
     490                        drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
     491                    }
    394492                }
    395493            }
     494#endif
    396495            d_ptr->paintedRegion = QRegion();
    397 
    398496            context()->swapBuffers();
    399497        } else {
     
    404502    }
    405503
     504    QGLContext *previous_ctx = const_cast<QGLContext *>(QGLContext::currentContext());
    406505    QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext);
    407     GLuint texture;
     506
     507    // QPainter::end() should have unbound the fbo, otherwise something is very wrong...
     508    Q_ASSERT(!d_ptr->fbo || !d_ptr->fbo->isBound());
     509
     510    if (ctx != previous_ctx) {
     511        ctx->makeCurrent();
     512    }
     513
     514    QSize size = widget->rect().size();
     515    if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) {
     516        rect = parent->rect();
     517        br = rect.translated(wOffset + offset);
     518        size = parent->size();
     519    }
     520
     521    glDisable(GL_SCISSOR_TEST);
     522
     523    if (d_ptr->fbo && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) {
     524        const int h = d_ptr->fbo->height();
     525
     526        const int sx0 = br.left();
     527        const int sx1 = br.left() + br.width();
     528        const int sy0 = h - (br.top() + br.height());
     529        const int sy1 = h - br.top();
     530
     531        const int tx0 = rect.left();
     532        const int tx1 = rect.left() + rect.width();
     533        const int ty0 = parent->height() - (rect.top() + rect.height());
     534        const int ty1 = parent->height() - rect.top();
     535
     536        if (window() == parent || d_ptr->fbo->format().samples() <= 1) {
     537            // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     538            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle());
     539
     540            glBlitFramebufferEXT(sx0, sy0, sx1, sy1,
     541                    tx0, ty0, tx1, ty1,
     542                    GL_COLOR_BUFFER_BIT,
     543                    GL_NEAREST);
     544
     545            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
     546        } else {
     547            // can't do sub-region blits with multisample FBOs
     548            QGLFramebufferObject *temp = qgl_fbo_pool()->acquire(d_ptr->fbo->size(), QGLFramebufferObjectFormat());
     549
     550            glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, temp->handle());
     551            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle());
     552
     553            glBlitFramebufferEXT(0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(),
     554                    0, 0, d_ptr->fbo->width(), d_ptr->fbo->height(),
     555                    GL_COLOR_BUFFER_BIT,
     556                    GL_NEAREST);
     557
     558            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, temp->handle());
     559            glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
     560
     561            glBlitFramebufferEXT(sx0, sy0, sx1, sy1,
     562                    tx0, ty0, tx1, ty1,
     563                    GL_COLOR_BUFFER_BIT,
     564                    GL_NEAREST);
     565
     566            glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
     567
     568            qgl_fbo_pool()->release(temp);
     569        }
     570    }
     571#if !defined(QT_OPENGL_ES_2)
     572    else {
     573        GLuint texture;
    408574    if (d_ptr->fbo) {
    409575        texture = d_ptr->fbo->texture();
     
    417583    }
    418584
    419     QSize size = widget->rect().size();
    420     if (ctx->format().doubleBuffer()) {
    421         rect = parent->rect();
    422         br = rect.translated(wOffset);
    423         size = parent->size();
    424     }
    425 
    426     ctx->makeCurrent();
    427 #ifdef Q_WS_MAC
    428     ctx->updatePaintDevice();
    429 #endif
    430     if (d_ptr->fbo)
    431         d_ptr->fbo->release();
    432 
    433     glMatrixMode(GL_MODELVIEW);
    434     glLoadIdentity();
    435 
    436     glMatrixMode(GL_PROJECTION);
    437     glLoadIdentity();
     585        glDisable(GL_DEPTH_TEST);
     586
     587        if (d_ptr->fbo) {
     588            d_ptr->fbo->release();
     589        } else {
     590            ctx->makeCurrent();
     591        }
     592
     593        glMatrixMode(GL_MODELVIEW);
     594        glLoadIdentity();
     595
     596        glMatrixMode(GL_PROJECTION);
     597        glLoadIdentity();
    438598#ifndef QT_OPENGL_ES
    439     glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
     599        glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
    440600#else
    441     glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
    442 #endif
    443     glViewport(0, 0, size.width(), size.height());
    444 
    445     glColor4f(1, 1, 1, 1);
    446     drawTexture(rect, texture, window()->size(), br);
     601        glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
     602#endif
     603        glViewport(0, 0, size.width(), size.height());
     604
     605        glColor4f(1, 1, 1, 1);
     606        drawTexture(rect, texture, window()->size(), br);
     607
     608        if (d_ptr->fbo)
     609            d_ptr->fbo->bind();
     610    }
     611#else
     612    // OpenGL/ES 2.0 version of the fbo blit.
     613    else if (d_ptr->fbo) {
     614        Q_UNUSED(target);
     615
     616        GLuint texture = d_ptr->fbo->texture();
     617
     618        glDisable(GL_DEPTH_TEST);
     619
     620        if (d_ptr->fbo->isBound())
     621            d_ptr->fbo->release();
     622
     623        glViewport(0, 0, size.width(), size.height());
     624
     625        QGLShaderProgram *blitProgram =
     626            QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram();
     627        blitProgram->bind();
     628        blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/);
     629
     630        // The shader manager's blit program does not multiply the
     631        // vertices by the pmv matrix, so we need to do the effect
     632        // of the orthographic projection here ourselves.
     633        QRectF r;
     634        qreal w = size.width() ? size.width() : 1.0f;
     635        qreal h = size.height() ? size.height() : 1.0f;
     636        r.setLeft((rect.left() / w) * 2.0f - 1.0f);
     637        if (rect.right() == (size.width() - 1))
     638            r.setRight(1.0f);
     639        else
     640            r.setRight((rect.right() / w) * 2.0f - 1.0f);
     641        r.setBottom((rect.top() / h) * 2.0f - 1.0f);
     642        if (rect.bottom() == (size.height() - 1))
     643            r.setTop(1.0f);
     644        else
     645            r.setTop((rect.bottom() / w) * 2.0f - 1.0f);
     646
     647        drawTexture(r, texture, window()->size(), br);
     648    }
     649#endif
    447650
    448651    if (ctx->format().doubleBuffer())
     
    450653    else
    451654        glFlush();
    452 
    453     if (d_ptr->fbo)
    454         d_ptr->fbo->bind();
    455 }
     655}
     656
    456657
    457658void QGLWindowSurface::setGeometry(const QRect &rect)
    458659{
    459660    QWindowSurface::setGeometry(rect);
    460 
    461     const GLenum target = qt_gl_preferredTextureTarget();
     661    d_ptr->geometry_updated = true;
     662}
     663
     664
     665void QGLWindowSurface::updateGeometry() {
     666    if (!d_ptr->geometry_updated)
     667        return;
     668    d_ptr->geometry_updated = false;
     669
     670
     671    QRect rect = geometry();
     672    hijackWindow(window());
     673    QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
     674
     675#ifdef Q_WS_MAC
     676    ctx->updatePaintDevice();
     677#endif
     678
     679    const GLenum target = GL_TEXTURE_2D;
    462680
    463681    if (rect.width() <= 0 || rect.height() <= 0)
     
    470688
    471689    if (d_ptr->ctx) {
    472         glBindTexture(target, d_ptr->tex_id);
    473         glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    474         glBindTexture(target, 0);
     690#ifndef QT_OPENGL_ES_2
     691        if (d_ptr->destructive_swap_buffers) {
     692            glBindTexture(target, d_ptr->tex_id);
     693            glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
     694            glBindTexture(target, 0);
     695        }
     696#endif
    475697        return;
    476698    }
    477699
    478     if (d_ptr->pb || !d_ptr->tried_pb) {
     700    if (d_ptr->destructive_swap_buffers
     701        && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
     702        && (d_ptr->fbo || !d_ptr->tried_fbo)
     703        && qt_gl_preferGL2Engine())
     704    {
     705        d_ptr->tried_fbo = true;
     706        ctx->d_ptr->internal_context = true;
     707        ctx->makeCurrent();
     708        delete d_ptr->fbo;
     709
     710        QGLFramebufferObjectFormat format;
     711        format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
     712        format.setInternalTextureFormat(GLenum(GL_RGBA));
     713        format.setTextureTarget(target);
     714
     715        if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
     716            format.setSamples(8);
     717
     718        d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);
     719
     720        if (d_ptr->fbo->isValid()) {
     721            qDebug() << "Created Window Surface FBO" << rect.size()
     722                     << "with samples" << d_ptr->fbo->format().samples();
     723            return;
     724        } else {
     725            qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back";
     726            delete d_ptr->fbo;
     727            d_ptr->fbo = 0;
     728        }
     729    }
     730
     731#if !defined(QT_OPENGL_ES_2)
     732    if (d_ptr->destructive_swap_buffers && (d_ptr->pb || !d_ptr->tried_pb)) {
    479733        d_ptr->tried_pb = true;
    480734
     
    491745
    492746        if (d_ptr->pb->isValid()) {
    493             qDebug() << "PB Sample buffers:" << d_ptr->pb->format().sampleBuffers();
     747            qDebug() << "Created Window Surface Pixelbuffer, Sample buffers:" << d_ptr->pb->format().sampleBuffers();
    494748            d_ptr->pb->makeCurrent();
    495749
     
    504758            glMatrixMode(GL_PROJECTION);
    505759            glLoadIdentity();
    506 #ifndef QT_OPENGL_ES
    507760            glOrtho(0, d_ptr->pb->width(), d_ptr->pb->height(), 0, -999999, 999999);
    508 #else
    509             glOrthof(0, d_ptr->pb->width(), d_ptr->pb->height(), 0, -999999, 999999);
    510 #endif
    511761
    512762            d_ptr->pb->d_ptr->qctx->d_func()->internal_context = true;
     
    518768        }
    519769    }
    520 
    521     if ((QGLExtensions::glExtensions & QGLExtensions::FramebufferObject) && (d_ptr->fbo || !d_ptr->tried_fbo)) {
    522         d_ptr->tried_fbo = true;
    523         hijackWindow(window());
    524         QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
    525         ctx->d_ptr->internal_context = true;
    526         ctx->makeCurrent();
    527         delete d_ptr->fbo;
    528         d_ptr->fbo = new QGLFramebufferObject(rect.size(), QGLFramebufferObject::CombinedDepthStencil,
    529                                               GLenum(target), GLenum(GL_RGBA));
    530 
    531         d_ptr->fbo->bind();
    532         if (d_ptr->fbo->isValid()) {
    533             return;
    534         } else {
    535             qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back";
    536             delete d_ptr->fbo;
    537             d_ptr->fbo = 0;
    538         }
    539     }
    540 
    541     hijackWindow(window());
    542     QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
     770#endif // !defined(QT_OPENGL_ES_2)
     771
    543772    ctx->makeCurrent();
    544773
    545     glGenTextures(1, &d_ptr->tex_id);
    546     glBindTexture(target, d_ptr->tex_id);
    547     glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    548 
    549     glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    550     glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    551     glBindTexture(target, 0);
     774#ifndef QT_OPENGL_ES_2
     775    if (d_ptr->destructive_swap_buffers) {
     776        glGenTextures(1, &d_ptr->tex_id);
     777        glBindTexture(target, d_ptr->tex_id);
     778        glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
     779
     780        glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     781        glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     782        glBindTexture(target, 0);
     783    }
     784#endif
    552785
    553786    qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;
     
    579812#endif
    580813
    581     const GLenum target = qt_gl_preferredTextureTarget();
     814    const GLenum target = GL_TEXTURE_2D;
    582815
    583816    glBindTexture(target, d_ptr->tex_id);
     
    592825static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br)
    593826{
    594     const GLenum target = qt_gl_preferredTextureTarget();
     827    const GLenum target = GL_TEXTURE_2D;
    595828    QRectF src = br.isEmpty()
    596829        ? QRectF(QPointF(), texSize)
     
    620853    qt_add_rect_to_array(rect, vertexArray);
    621854
     855#if !defined(QT_OPENGL_ES_2)
    622856    glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
    623857    glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
     
    634868    glDisable(target);
    635869    glBindTexture(target, 0);
     870#else
     871    glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray);
     872    glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray);
     873
     874    glBindTexture(target, tex_id);
     875
     876    glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     877    glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     878    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
     879    glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
     880    glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
     881
     882    glBindTexture(target, 0);
     883#endif
    636884}
    637885
  • trunk/src/opengl/qwindowsurface_gl_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    5757#include <qgl.h>
    5858#include <private/qwindowsurface_p.h>
     59#include <private/qglpaintdevice_p.h>
    5960
    6061QT_BEGIN_NAMESPACE
     
    6667struct QGLWindowSurfacePrivate;
    6768
    68 class QGLWindowSurface : public QWindowSurface, public QPaintDevice
     69class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice
    6970{
     71public:
     72    QPaintEngine* paintEngine() const;
     73    void endPaint();
     74    QSize size() const;
     75    int metric(PaintDeviceMetric m) const;
     76    QGLContext* context() const;
     77    QGLWindowSurfacePrivate* d;
     78};
     79
     80class QGLWindowSurface : public QObject, public QWindowSurface // , public QPaintDevice
     81{
     82    Q_OBJECT
    7083public:
    7184    QGLWindowSurface(QWidget *window);
     
    7588    void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
    7689    void setGeometry(const QRect &rect);
     90    void updateGeometry();
    7791    bool scroll(const QRegion &area, int dx, int dy);
    7892
     
    86100    static QGLFormat surfaceFormat;
    87101
    88     QPaintEngine *paintEngine() const;
    89 
    90 protected:
    91     int metric(PaintDeviceMetric metric) const;
     102private slots:
     103    void deleted(QObject *object);
    92104
    93105private:
  • trunk/src/opengl/util/composition_mode_colorburn.glsl

    r2 r561  
    66{
    77    vec4 result;
    8     result.rgb = mix(src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
    9                      src.a * (src.rgb * dst.a + dst.rgb * src.a - src.a * dst.a) / max(src.rgb, 0.00001) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
     8    result.rgb = mix(src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
     9                     src.a * (src.rgb * dst.a + dst.rgb * src.a - src.a * dst.a) / max(src.rgb, 0.00001) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
    1010                     step(src.a * dst.a, src.rgb * dst.a + dst.rgb * src.a));
    1111    result.a = src.a + dst.a - src.a * dst.a;
  • trunk/src/opengl/util/composition_mode_colordodge.glsl

    r2 r561  
    66{
    77    vec4 result;
    8     vec3 temp = src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
    9     result.rgb = mix(dst.rgb * src.a / max(1 - src.rgb / max(src.a, 0.000001), 0.000001) + temp,
     8    vec3 temp = src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
     9    result.rgb = mix(dst.rgb * src.a / max(1.0 - src.rgb / max(src.a, 0.000001), 0.000001) + temp,
    1010                     src.a * dst.a + temp,
    1111                     step(src.a * dst.a, src.rgb * dst.a + dst.rgb * src.a));
  • trunk/src/opengl/util/composition_mode_darken.glsl

    r2 r561  
    44{
    55    vec4 result;
    6     result.rgb = min(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
     6    result.rgb = min(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
    77    result.a = src.a + dst.a - src.a * dst.a;
    88    return result;
  • trunk/src/opengl/util/composition_mode_difference.glsl

    r2 r561  
    44{
    55    vec4 result;
    6     result.rgb = src.rgb + dst.rgb - 2 * min(src.rgb * dst.a, dst.rgb * src.a);
     6    result.rgb = src.rgb + dst.rgb - 2.0 * min(src.rgb * dst.a, dst.rgb * src.a);
    77    result.a = src.a + dst.a - src.a * dst.a;
    88    return result;
  • trunk/src/opengl/util/composition_mode_exclusion.glsl

    r2 r561  
    44{
    55    vec4 result;
    6     result.rgb = (src.rgb * dst.a + dst.rgb * src.a - 2 * src.rgb * dst.rgb) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
     6    result.rgb = (src.rgb * dst.a + dst.rgb * src.a - 2.0 * src.rgb * dst.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
    77    result.a = src.a + dst.a - src.a * dst.a;
    88    return result;
  • trunk/src/opengl/util/composition_mode_hardlight.glsl

    r2 r561  
    66{
    77    vec4 result;
    8     result.rgb = mix(2 * src.rgb * dst.rgb + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
    9                      src.a * dst.a - 2 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
    10                      step(src.a, 2 * src.rgb));
     8    result.rgb = mix(2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
     9                     src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
     10                     step(src.a, 2.0 * src.rgb));
    1111    result.a = src.a + dst.a - src.a * dst.a;
    1212
  • trunk/src/opengl/util/composition_mode_lighten.glsl

    r2 r561  
    44{
    55    vec4 result;
    6     result.rgb = max(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
     6    result.rgb = max(src.rgb * dst.a, dst.rgb * src.a) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
    77    result.a = src.a + dst.a - src.a * dst.a;
    88    return result;
  • trunk/src/opengl/util/composition_mode_multiply.glsl

    r2 r561  
    44{
    55    vec4 result;
    6     result.rgb = src.rgb * dst.rgb + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
     6    result.rgb = src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
    77    result.a = src.a + dst.a - src.a * dst.a;
    88    return result;
  • trunk/src/opengl/util/composition_mode_overlay.glsl

    r2 r561  
    66{
    77    vec4 result;
    8     result.rgb = mix(2 * src.rgb * dst.rgb + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
    9                      src.a * dst.a - 2 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a),
    10                      step(dst.a, 2 * dst.rgb));
     8    result.rgb = mix(2.0 * src.rgb * dst.rgb + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
     9                     src.a * dst.a - 2.0 * (dst.a - dst.rgb) * (src.a - src.rgb) + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a),
     10                     step(dst.a, 2.0 * dst.rgb));
    1111    result.a = src.a + dst.a - src.a * dst.a;
    1212    return result;
  • trunk/src/opengl/util/composition_mode_softlight.glsl

    r2 r561  
    1 // Dca' = 2.Sca < Sa ?
    2 //        Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) :
    3 //          (8.Dca <= Da ?
    4 //           Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) :
    5 //           (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa))
     1// if 2.Sca <= Sa
     2//     Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
     3// otherwise if 2.Sca > Sa and 4.Dca <= Da
     4//     Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
     5// otherwise if 2.Sca > Sa and 4.Dca > Da
     6//     Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa)
    67// Da'  = Sa + Da - Sa.Da
     8
    79vec4 composite(vec4 src, vec4 dst)
    810{
    911    vec4 result;
    1012    float da = max(dst.a, 0.00001);
    11     result.rgb = mix(dst.rgb * (src.a - (1 - dst.rgb / da) * (2 * src.rgb - src.a)),
    12                      mix(dst.rgb * (src.a - (1 - dst.rgb / da) * (2 * src.rgb - src.a) * (3 - 8 * dst.rgb / da)),
    13                          (dst.rgb * src.a + (sqrt(dst.rgb / da) * dst.a - dst.rgb) * (2 * src.rgb - src.a)),
    14                          step(dst.a, 8 * dst.rgb)),
    15                      step(src.a, 2 * src.rgb)) + src.rgb * (1 - dst.a) + dst.rgb * (1 - src.a);
     13    vec3 dst_np = dst.rgb / da;
     14    result.rgb = mix(dst.rgb * (src.a + (2.0 * src.rgb - src.a) * (1.0 - dst_np)),
     15                     mix(dst.rgb * src.a + dst.a * (2.0 * src.rgb - src.a) * ((16.0 * dst_np - 12.0) * dst_np + 3.0) * dst_np,
     16                         dst.rgb * src.a + dst.a * (2.0 * src.rgb - src.a) * (sqrt(dst_np) - dst_np),
     17                         step(dst.a, 4.0 * dst.rgb)),
     18                     step(src.a, 2.0 * src.rgb))
     19                 + src.rgb * (1.0 - dst.a) + dst.rgb * (1.0 - src.a);
    1620    result.a = src.a + dst.a - src.a * dst.a;
    1721    return result;
  • trunk/src/opengl/util/conical_brush.glsl

    r2 r561  
    2121    if (abs(A.y) == abs(A.x))
    2222        A.y += 0.002;
    23     float t = (atan2(-A.y, A.x) + angle) / (2.0 * M_PI);
     23    float t = (atan(-A.y, A.x) + angle) / (2.0 * M_PI);
    2424    float val = t - floor(t);
    2525    return texture1D(palette, val);
  • trunk/src/opengl/util/ellipse_aa.glsl

    r2 r561  
    1 #include "ellipse_functions.glsl"
     1uniform vec3 inv_matrix_m0;
     2uniform vec3 inv_matrix_m1;
     3uniform vec3 inv_matrix_m2;
     4
     5uniform vec2 ellipse_offset;
     6
     7// ellipse equation
     8
     9// s^2/a^2 + t^2/b^2 = 1
     10//
     11// implicit equation:
     12// g(s,t) = 1 - s^2/r_s^2 - t^2/r_t^2
     13
     14// distance from ellipse:
     15// grad = [dg/dx dg/dy]
     16// d(s, t) ~= g(s, t) / |grad|
     17
     18// dg/dx = dg/ds * ds/dx + dg/dt * dt/dx
     19// dg/dy = dg/ds * ds/dy + dg/dt * dt/dy
     20
     21float ellipse_aa()
     22{
     23    mat3 mat;
     24
     25    mat[0] = inv_matrix_m0;
     26    mat[1] = inv_matrix_m1;
     27    mat[2] = inv_matrix_m2;
     28
     29    vec3 hcoords = mat * vec3(gl_FragCoord.xy + ellipse_offset, 1);
     30    float inv_w = 1.0 / hcoords.z;
     31    vec2 st = hcoords.xy * inv_w;
     32
     33    vec4 xy = vec4(mat[0].xy, mat[1].xy);
     34    vec2 h = vec2(mat[0].z, mat[1].z);
     35
     36    vec4 dstdxy = (xy.xzyw - h.xyxy * st.xxyy) * inv_w;
     37
     38    //dstdxy.x = (mat[0].x - mat[0].z * st.x) * inv_w; // ds/dx
     39    //dstdxy.y = (mat[1].x - mat[1].z * st.x) * inv_w; // ds/dy
     40    //dstdxy.z = (mat[0].y - mat[0].z * st.y) * inv_w; // dt/dx
     41    //dstdxy.w = (mat[1].y - mat[1].z * st.y) * inv_w; // dt/dy
     42
     43    vec2 inv_r = gl_TexCoord[0].xy;
     44    vec2 n = st * inv_r;
     45    float g = 1.0 - dot(n, n);
     46
     47    vec2 dgdst = -2.0 * n * inv_r;
     48
     49    vec2 grad = vec2(dot(dgdst, dstdxy.xz),
     50                     dot(dgdst, dstdxy.yw));
     51
     52    return smoothstep(-0.5, 0.5, g * inversesqrt(dot(grad, grad)));
     53}
    254
    355void main()
    456{
    5     gl_FragColor = ellipse_aa();
     57    gl_FragColor = ellipse_aa().xxxx;
    658}
  • trunk/src/opengl/util/fragmentprograms_p.h

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
    4040****************************************************************************/
    41 #ifndef FRAGMENTPROGRAMS_H
    42 #define FRAGMENTPROGRAMS_H
     41
     42#ifndef FRAGMENTPROGRAMS_P_H
     43#define FRAGMENTPROGRAMS_P_H
    4344
    4445//
     
    7273    VAR_FMP,
    7374    VAR_INV_MATRIX_M0,
    74     VAR_ANGLE,
     75    VAR_ANGLE
    7576};
    7677
     
    8182    FRAGMENT_PROGRAM_BRUSH_LINEAR,
    8283    FRAGMENT_PROGRAM_BRUSH_TEXTURE,
    83     FRAGMENT_PROGRAM_BRUSH_PATTERN,
     84    FRAGMENT_PROGRAM_BRUSH_PATTERN
    8485};
    8586
     
    110111    COMPOSITION_MODES_EXCLUSION_NOMASK,
    111112    COMPOSITION_MODE_BLEND_MODE_MASK,
    112     COMPOSITION_MODE_BLEND_MODE_NOMASK,
     113    COMPOSITION_MODE_BLEND_MODE_NOMASK
    113114};
    114115
    115116enum FragmentMaskType {
    116117    FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA,
    117     FRAGMENT_PROGRAM_MASK_ELLIPSE_AA,
     118    FRAGMENT_PROGRAM_MASK_ELLIPSE_AA
    118119};
    119120
     
    132133    "TEMP R3;\n"
    133134    "TEMP R4;\n"
    134     "ADD R4.x, fragment.position, c[0];\n"
     135    "ADD R3.z, fragment.position.x, c[0].x;\n"
    135136    "ADD R0.y, fragment.position, -c[0].x;\n"
    136     "MAX R2.x, R0.y, fragment.texcoord[0].y;\n"
     137    "MAX R4.x, fragment.texcoord[0].y, R0.y;\n"
    137138    "ADD R0.x, fragment.position.y, c[0];\n"
    138     "MIN R2.y, R0.x, fragment.texcoord[0].x;\n"
    139     "ADD R3.x, fragment.position, -c[0];\n"
    140     "ADD R1.zw, -fragment.texcoord[0], -fragment.texcoord[0];\n"
    141     "MOV R3.y, R4.x;\n"
    142     "MOV R0.yw, R2.x;\n"
    143     "MOV R0.xz, R2.y;\n"
     139    "MIN R3.w, R0.x, fragment.texcoord[0].x;\n"
     140    "ADD R2.z, fragment.position.x, -c[0].x;\n"
     141    "MOV R2.w, R3.z;\n"
     142    "MOV R0.yw, R4.x;\n"
     143    "MOV R0.xz, R3.w;\n"
    144144    "MAD R0, fragment.texcoord[1].xxzz, R0, fragment.texcoord[1].yyww;\n"
    145     "MAD R1.xy, fragment.position.x, c[0].y, -R0.zwzw;\n"
    146     "MOV R0.w, R1.x;\n"
    147     "MOV R1.x, R0.y;\n"
    148     "MOV R0.z, R0.x;\n"
    149     "SGE R2.zw, R1.xyxy, R0;\n"
    150     "MAX R0.xy, R0.zwzw, R1;\n"
    151     "MIN R0.zw, R0, R1.xyxy;\n"
    152     "MAD R2.zw, R2, R1, fragment.texcoord[0];\n"
    153     "ADD R1, R3.xyxy, -R0.zzww;\n"
    154     "MAD R1, R1, R2.zzww, R2.x;\n"
    155     "ADD R3.zw, R0.xyxy, R0;\n"
    156     "ADD R3.y, R2, -R2.x;\n"
    157     "ADD R2.zw, R1.xyyw, -R2.x;\n"
    158     "ADD R4.zw, R4.x, -R0;\n"
    159     "MUL R2.zw, R4, R2;\n"
    160     "ADD R4.zw, R1.xyyw, R1.xyxz;\n"
    161     "ADD R1.xz, R2.y, -R1;\n"
    162     "MAD R2.zw, -R2, c[0].x, R3.y;\n"
    163     "MAD R3.zw, R3, c[0].x, -R3.x;\n"
    164     "MAD R3.zw, R3, R3.y, -R2;\n"
    165     "ADD R1.y, R4.x, -R3.x;\n"
    166     "MAD R4.zw, -R4, c[0].x, R2.y;\n"
    167     "MUL R4.zw, R4, R1.y;\n"
    168     "ADD R1.yw, R0.xxzy, -R3.x;\n"
    169     "MUL R1.xy, R1.xzzw, R1.ywzw;\n"
    170     "MAD R1.zw, R1.xyxy, c[0].x, -R4;\n"
    171     "SGE R1.xy, R4.x, R0;\n"
    172     "MUL R1.zw, R1.xyxy, R1;\n"
    173     "MAD R1.xy, R1, R3.zwzw, R2.zwzw;\n"
    174     "SGE R2.zw, R3.x, R0;\n"
    175     "ADD R1.zw, R4, R1;\n"
    176     "ADD R1.zw, R1, -R1.xyxy;\n"
    177     "MAD R1.xy, R2.zwzw, R1.zwzw, R1;\n"
    178     "ADD R1.xy, R1, -R3.y;\n"
    179     "SGE R0.zw, R4.x, R0;\n"
    180     "MAD R0.zw, R0, R1.xyxy, R3.y;\n"
    181     "SGE R0.xy, R0, R3.x;\n"
    182     "MUL R0.xy, R0.zwzw, R0;\n"
    183     "ADD R0.x, R3.y, -R0;\n"
    184     "SGE R0.z, R2.y, R2.x;\n"
    185     "ADD R0.x, R0, -R0.y;\n"
     145    "MAD R0.zw, fragment.position.x, c[0].y, -R0;\n"
     146    "MOV R2.x, R0;\n"
     147    "MOV R2.y, R0.z;\n"
     148    "MOV R1.w, R0;\n"
     149    "MOV R1.z, R0.y;\n"
     150    "MIN R1.xy, R2, R1.zwzw;\n"
     151    "SGE R0.xy, R1.zwzw, R2;\n"
     152    "ADD R0.zw, -fragment.texcoord[0], -fragment.texcoord[0];\n"
     153    "MAD R3.xy, R0, R0.zwzw, fragment.texcoord[0].zwzw;\n"
     154    "ADD R0, -R1.xxyy, R2.zwzw;\n"
     155    "MAD R0, R0, R3.xxyy, R4.x;\n"
     156    "ADD R3.xy, R0.ywzw, R0.xzzw;\n"
     157    "ADD R4.zw, R3.w, -R0.xyxz;\n"
     158    "ADD R0.zw, -R4.x, R0.xyyw;\n"
     159    "ADD R0.xy, R3.z, -R1;\n"
     160    "MAX R1.zw, R2.xyxy, R1;\n"
     161    "MUL R0.xy, R0, R0.zwzw;\n"
     162    "MAD R3.xy, -R3, c[0].x, R3.w;\n"
     163    "ADD R2.w, R3.z, -R2.z;\n"
     164    "MUL R2.xy, R3, R2.w;\n"
     165    "ADD R2.w, R3, -R4.x;\n"
     166    "ADD R3.xy, -R2.z, R1.zwzw;\n"
     167    "MUL R3.xy, R4.zwzw, R3;\n"
     168    "ADD R4.zw, R1.xyxy, R1;\n"
     169    "MAD R0.zw, R4, c[0].x, -R2.z;\n"
     170    "MAD R0.xy, -R0, c[0].x, R2.w;\n"
     171    "MAD R4.zw, R0, R2.w, -R0.xyxy;\n"
     172    "SGE R0.zw, R3.z, R1;\n"
     173    "MAD R0.xy, R0.zwzw, R4.zwzw, R0;\n"
     174    "MAD R3.xy, R3, c[0].x, -R2;\n"
     175    "MAD R0.zw, R0, R3.xyxy, R2.xyxy;\n"
     176    "ADD R2.xy, R0.zwzw, -R0;\n"
     177    "SGE R0.zw, R2.z, R1.xyxy;\n"
     178    "MAD R0.xy, R0.zwzw, R2, R0;\n"
     179    "SGE R0.zw, R1, R2.z;\n"
     180    "ADD R0.xy, R0, -R2.w;\n"
     181    "SGE R1.xy, R3.z, R1;\n"
     182    "MAD R0.xy, R1, R0, R2.w;\n"
     183    "MAD R0.x, -R0, R0.z, R2.w;\n"
     184    "SGE R0.z, R3.w, R4.x;\n"
     185    "MAD R0.x, -R0.y, R0.w, R0;\n"
    186186    "MUL result.color, R0.x, R0.z;\n"
    187187    "END\n"
     
    196196    "TEMP R1;\n"
    197197    "TEMP R2;\n"
    198     "ADD R0.xy, fragment.position, c[0];\n"
    199     "MUL R1.xyz, R0.y, c[2];\n"
    200     "MAD R0.xyz, R0.x, c[1], R1;\n"
    201     "ADD R0.xyz, R0, c[3];\n"
     198    "ADD R0.xy, fragment.position, c[3];\n"
     199    "MUL R1.xyz, R0.y, c[1];\n"
     200    "MAD R0.xyz, R0.x, c[0], R1;\n"
     201    "ADD R0.xyz, R0, c[2];\n"
    202202    "RCP R2.z, R0.z;\n"
    203203    "MUL R0.zw, R0.xyxy, R2.z;\n"
    204204    "MUL R2.xy, R0.zwzw, fragment.texcoord[0];\n"
    205     "MOV R1.xy, c[1];\n"
    206     "MOV R1.zw, c[2].xyxy;\n"
    207     "MOV R0.x, c[1].z;\n"
    208     "MOV R0.y, c[2].z;\n"
    209     "MAD R0, -R0.xyxy, R0.zzww, R1.xzyw;\n"
     205    "MOV R1.xy, c[0];\n"
     206    "MOV R1.zw, c[1].xyxy;\n"
     207    "MOV R0.x, c[0].z;\n"
     208    "MOV R0.y, c[1].z;\n"
     209    "MAD R0, R0.zzww, -R0.xyxy, R1.xzyw;\n"
    210210    "MUL R1.xy, R2, fragment.texcoord[0];\n"
    211     "MUL R0, R0, R2.z;\n"
     211    "MUL R0, R2.z, R0;\n"
    212212    "MUL R1.xy, R1, c[4].x;\n"
    213213    "MUL R1.zw, R1.xyxy, R0.xyxz;\n"
    214     "MUL R0.xy, R1, R0.ywzw;\n"
    215     "ADD R0.w, R0.x, R0.y;\n"
    216     "MUL R0.xy, R2, R2;\n"
     214    "MUL R0.zw, R1.xyxy, R0.xyyw;\n"
     215    "ADD R0.y, R0.z, R0.w;\n"
     216    "ADD R0.x, R1.z, R1.w;\n"
     217    "MUL R0.xy, R0, R0;\n"
    217218    "ADD R0.x, R0, R0.y;\n"
    218     "ADD R0.z, R1, R1.w;\n"
    219     "MUL R0.zw, R0, R0;\n"
    220     "ADD R0.y, R0.z, R0.w;\n"
    221     "RSQ R0.y, R0.y;\n"
    222     "ADD R0.x, -R0, c[4].y;\n"
    223     "MAD_SAT R0.x, R0.y, R0, -c[4].z;\n"
     219    "MUL R0.zw, R2.xyxy, R2.xyxy;\n"
     220    "ADD R0.z, R0, R0.w;\n"
     221    "ADD R0.y, -R0.z, c[4];\n"
     222    "RSQ R0.x, R0.x;\n"
     223    "MAD_SAT R0.x, R0, R0.y, -c[4].z;\n"
    224224    "MUL R0.y, -R0.x, c[4].w;\n"
    225225    "ADD R0.y, R0, c[5].x;\n"
     
    231231static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    232232    "!!ARBfp1.0\n"
    233     "PARAM c[7] = { program.local[0..3],\n"
    234     "           { 1 },\n"
    235     "           program.local[5..6] };\n"
     233    "PARAM c[7] = { program.local[0..5],\n"
     234    "           { 1 } };\n"
    236235    "TEMP R0;\n"
    237236    "TEMP R1;\n"
     
    239238    "TEMP R3;\n"
    240239    "MUL R0.xy, fragment.position, c[3];\n"
    241     "TEX R1, R0, texture[0], 2D;\n"
    242     "MUL R0.xyz, R1, c[6].y;\n"
    243     "MUL R2.xyz, R0, fragment.color.primary.w;\n"
    244     "MUL R0.xyz, fragment.color.primary, c[6].x;\n"
    245     "MAD R2.xyz, R0, R1.w, R2;\n"
    246     "ADD R3.xy, fragment.position, c[0];\n"
    247     "ADD R0.w, -R1, c[4].x;\n"
    248     "MUL R0.xyz, fragment.color.primary, c[5].y;\n"
    249     "MAD R2.xyz, R0, R0.w, R2;\n"
    250     "MUL R0.xyz, R1, c[5].z;\n"
    251     "ADD R0.w, -fragment.color.primary, c[4].x;\n"
    252     "MAD R2.xyz, R0, R0.w, R2;\n"
    253     "ADD R0.y, -R1.w, c[4].x;\n"
    254     "MUL R0.x, fragment.color.primary.w, R1.w;\n"
    255     "MUL R0.y, fragment.color.primary.w, R0;\n"
    256     "MUL R0.z, R1.w, R0.w;\n"
    257     "DP3 R2.w, R0, c[5];\n"
    258     "MUL R3.xy, R3, c[1];\n"
    259     "TEX R0, R3, texture[1], 2D;\n"
    260     "ADD R2, R2, -R1;\n"
    261     "DP4 R0.x, R0, c[2];\n"
    262     "MAD result.color, R0.x, R2, R1;\n"
     240    "TEX R0, R0, texture[0], 2D;\n"
     241    "MUL R1.xyz, R0, c[0].y;\n"
     242    "MUL R2.xyz, fragment.color.primary.w, R1;\n"
     243    "MUL R1.xyz, fragment.color.primary, c[0].x;\n"
     244    "MAD R2.xyz, R0.w, R1, R2;\n"
     245    "ADD R3.xy, fragment.position, c[4];\n"
     246    "ADD R1.w, -R0, c[6].x;\n"
     247    "MUL R1.xyz, fragment.color.primary, c[1].y;\n"
     248    "MAD R2.xyz, R1.w, R1, R2;\n"
     249    "MUL R1.xyz, R0, c[1].z;\n"
     250    "ADD R2.w, -fragment.color.primary, c[6].x;\n"
     251    "MAD R2.xyz, R2.w, R1, R2;\n"
     252    "MUL R1.z, R0.w, R2.w;\n"
     253    "MUL R1.x, fragment.color.primary.w, R0.w;\n"
     254    "MUL R1.y, fragment.color.primary.w, R1.w;\n"
     255    "DP3 R2.w, R1, c[1];\n"
     256    "MUL R3.xy, R3, c[2];\n"
     257    "TEX R1, R3, texture[1], 2D;\n"
     258    "ADD R2, R2, -R0;\n"
     259    "DP4 R1.x, R1, c[5];\n"
     260    "MAD result.color, R1.x, R2, R0;\n"
    263261    "END\n"
    264262    ;
     
    271269    "TEMP R1;\n"
    272270    "TEMP R2;\n"
    273     "MUL R0.xy, fragment.position, c[3];\n"
    274     "TEX R1, R0, texture[0], 2D;\n"
    275     "ADD R0.x, -R1.w, c[4];\n"
    276     "MUL R0.xyz, fragment.color.primary, R0.x;\n"
    277     "MAD R0.xyz, fragment.color.primary, R1, R0;\n"
    278     "ADD R0.w, -fragment.color.primary, c[4].x;\n"
    279     "MAD R2.xyz, R1, R0.w, R0;\n"
    280     "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    281     "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    282     "ADD R0.xy, fragment.position, c[0];\n"
    283     "MUL R0.xy, R0, c[1];\n"
    284     "TEX R0, R0, texture[1], 2D;\n"
    285     "ADD R2, R2, -R1;\n"
    286     "DP4 R0.x, R0, c[2];\n"
    287     "MAD result.color, R0.x, R2, R1;\n"
     271    "MUL R0.xy, fragment.position, c[1];\n"
     272    "TEX R0, R0, texture[0], 2D;\n"
     273    "ADD R1.x, -R0.w, c[4];\n"
     274    "MUL R1.xyz, fragment.color.primary, R1.x;\n"
     275    "MAD R1.xyz, fragment.color.primary, R0, R1;\n"
     276    "ADD R1.w, -fragment.color.primary, c[4].x;\n"
     277    "MAD R2.xyz, R0, R1.w, R1;\n"
     278    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
     279    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
     280    "ADD R1.xy, fragment.position, c[2];\n"
     281    "MUL R1.xy, R1, c[0];\n"
     282    "TEX R1, R1, texture[1], 2D;\n"
     283    "ADD R2, R2, -R0;\n"
     284    "DP4 R1.x, R1, c[3];\n"
     285    "MAD result.color, R1.x, R2, R0;\n"
    288286    "END\n"
    289287    ;
     
    295293    "TEMP R1;\n"
    296294    "TEMP R2;\n"
    297     "MUL R0.xy, fragment.position, c[3];\n"
    298     "TEX R1, R0, texture[0], 2D;\n"
    299     "ADD R0.xy, fragment.position, c[0];\n"
    300     "ADD R2, fragment.color.primary, R1;\n"
    301     "MUL R0.xy, R0, c[1];\n"
    302     "MAD R2, -fragment.color.primary, R1, R2;\n"
    303     "TEX R0, R0, texture[1], 2D;\n"
    304     "ADD R2, R2, -R1;\n"
    305     "DP4 R0.x, R0, c[2];\n"
    306     "MAD result.color, R0.x, R2, R1;\n"
     295    "MUL R0.xy, fragment.position, c[1];\n"
     296    "TEX R0, R0, texture[0], 2D;\n"
     297    "ADD R1.xy, fragment.position, c[2];\n"
     298    "ADD R2, fragment.color.primary, R0;\n"
     299    "MUL R1.xy, R1, c[0];\n"
     300    "MAD R2, -fragment.color.primary, R0, R2;\n"
     301    "TEX R1, R1, texture[1], 2D;\n"
     302    "ADD R2, R2, -R0;\n"
     303    "DP4 R1.x, R1, c[3];\n"
     304    "MAD result.color, R1.x, R2, R0;\n"
    307305    "END\n"
    308306    ;
     
    316314    "TEMP R2;\n"
    317315    "TEMP R3;\n"
    318     "MUL R0.xy, fragment.position, c[3];\n"
     316    "MUL R0.xy, fragment.position, c[1];\n"
    319317    "TEX R1, R0, texture[0], 2D;\n"
    320318    "ADD R0.w, -R1, c[4].y;\n"
     
    337335    "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    338336    "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    339     "ADD R0.xy, fragment.position, c[0];\n"
    340     "MUL R0.xy, R0, c[1];\n"
     337    "ADD R0.xy, fragment.position, c[2];\n"
     338    "MUL R0.xy, R0, c[0];\n"
    341339    "TEX R0, R0, texture[1], 2D;\n"
    342340    "ADD R2, R2, -R1;\n"
    343     "DP4 R0.x, R0, c[2];\n"
     341    "DP4 R0.x, R0, c[3];\n"
    344342    "MAD result.color, R0.x, R2, R1;\n"
    345343    "END\n"
     
    353351    "TEMP R1;\n"
    354352    "TEMP R2;\n"
    355     "MUL R0.xy, fragment.position, c[3];\n"
    356     "TEX R1, R0, texture[0], 2D;\n"
    357     "MUL R2.xyz, R1, fragment.color.primary.w;\n"
    358     "MUL R0.xyz, fragment.color.primary, R1.w;\n"
    359     "MIN R0.xyz, R0, R2;\n"
    360     "ADD R0.w, -R1, c[4].x;\n"
    361     "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n"
    362     "ADD R0.w, -fragment.color.primary, c[4].x;\n"
    363     "MAD R2.xyz, R1, R0.w, R0;\n"
    364     "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    365     "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    366     "ADD R0.xy, fragment.position, c[0];\n"
    367     "MUL R0.xy, R0, c[1];\n"
    368     "TEX R0, R0, texture[1], 2D;\n"
    369     "ADD R2, R2, -R1;\n"
    370     "DP4 R0.x, R0, c[2];\n"
    371     "MAD result.color, R0.x, R2, R1;\n"
     353    "MUL R0.xy, fragment.position, c[1];\n"
     354    "TEX R0, R0, texture[0], 2D;\n"
     355    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
     356    "MUL R1.xyz, fragment.color.primary, R0.w;\n"
     357    "MIN R1.xyz, R1, R2;\n"
     358    "ADD R1.w, -R0, c[4].x;\n"
     359    "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
     360    "ADD R1.w, -fragment.color.primary, c[4].x;\n"
     361    "MAD R2.xyz, R0, R1.w, R1;\n"
     362    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
     363    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
     364    "ADD R1.xy, fragment.position, c[2];\n"
     365    "MUL R1.xy, R1, c[0];\n"
     366    "TEX R1, R1, texture[1], 2D;\n"
     367    "ADD R2, R2, -R0;\n"
     368    "DP4 R1.x, R1, c[3];\n"
     369    "MAD result.color, R1.x, R2, R0;\n"
    372370    "END\n"
    373371    ;
     
    380378    "TEMP R1;\n"
    381379    "TEMP R2;\n"
    382     "MUL R0.xy, fragment.position, c[3];\n"
    383     "TEX R1, R0, texture[0], 2D;\n"
    384     "MUL R2.xyz, R1, fragment.color.primary.w;\n"
    385     "MUL R0.xyz, fragment.color.primary, R1.w;\n"
    386     "MAX R0.xyz, R0, R2;\n"
    387     "ADD R0.w, -R1, c[4].x;\n"
    388     "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n"
    389     "ADD R0.w, -fragment.color.primary, c[4].x;\n"
    390     "MAD R2.xyz, R1, R0.w, R0;\n"
    391     "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    392     "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    393     "ADD R0.xy, fragment.position, c[0];\n"
    394     "MUL R0.xy, R0, c[1];\n"
    395     "TEX R0, R0, texture[1], 2D;\n"
    396     "ADD R2, R2, -R1;\n"
    397     "DP4 R0.x, R0, c[2];\n"
    398     "MAD result.color, R0.x, R2, R1;\n"
     380    "MUL R0.xy, fragment.position, c[1];\n"
     381    "TEX R0, R0, texture[0], 2D;\n"
     382    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
     383    "MUL R1.xyz, fragment.color.primary, R0.w;\n"
     384    "MAX R1.xyz, R1, R2;\n"
     385    "ADD R1.w, -R0, c[4].x;\n"
     386    "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
     387    "ADD R1.w, -fragment.color.primary, c[4].x;\n"
     388    "MAD R2.xyz, R0, R1.w, R1;\n"
     389    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
     390    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
     391    "ADD R1.xy, fragment.position, c[2];\n"
     392    "MUL R1.xy, R1, c[0];\n"
     393    "TEX R1, R1, texture[1], 2D;\n"
     394    "ADD R2, R2, -R0;\n"
     395    "DP4 R1.x, R1, c[3];\n"
     396    "MAD result.color, R1.x, R2, R0;\n"
    399397    "END\n"
    400398    ;
     
    403401    "!!ARBfp1.0\n"
    404402    "PARAM c[5] = { program.local[0..3],\n"
    405     "           { 1, 1e-06 } };\n"
    406     "TEMP R0;\n"
    407     "TEMP R1;\n"
    408     "TEMP R2;\n"
    409     "TEMP R3;\n"
    410     "MUL R0.xy, fragment.position, c[3];\n"
     403    "           { 1, 1e-006 } };\n"
     404    "TEMP R0;\n"
     405    "TEMP R1;\n"
     406    "TEMP R2;\n"
     407    "TEMP R3;\n"
     408    "MUL R0.xy, fragment.position, c[1];\n"
    411409    "TEX R0, R0, texture[0], 2D;\n"
    412     "ADD R1.y, -fragment.color.primary.w, c[4].x;\n"
    413     "MAX R1.x, fragment.color.primary.w, c[4].y;\n"
    414     "MUL R2.xyz, R0, R1.y;\n"
     410    "ADD R1.x, -fragment.color.primary.w, c[4];\n"
     411    "MAX R1.y, fragment.color.primary.w, c[4];\n"
     412    "MUL R2.xyz, R0, R1.x;\n"
    415413    "ADD R1.w, -R0, c[4].x;\n"
    416414    "MAD R3.xyz, fragment.color.primary, R1.w, R2;\n"
    417     "RCP R1.x, R1.x;\n"
    418     "MAD R1.xyz, -fragment.color.primary, R1.x, c[4].x;\n"
     415    "RCP R1.y, R1.y;\n"
     416    "MAD R1.xyz, -fragment.color.primary, R1.y, c[4].x;\n"
    419417    "MAX R1.xyz, R1, c[4].y;\n"
    420     "MUL R2.xyz, R0, fragment.color.primary.w;\n"
     418    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
    421419    "MUL R1.w, fragment.color.primary, R0;\n"
    422420    "RCP R1.x, R1.x;\n"
     
    431429    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
    432430    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
    433     "ADD R1.xy, fragment.position, c[0];\n"
    434     "MUL R1.xy, R1, c[1];\n"
     431    "ADD R1.xy, fragment.position, c[2];\n"
     432    "MUL R1.xy, R1, c[0];\n"
    435433    "TEX R1, R1, texture[1], 2D;\n"
    436434    "ADD R2, R2, -R0;\n"
    437     "DP4 R1.x, R1, c[2];\n"
     435    "DP4 R1.x, R1, c[3];\n"
    438436    "MAD result.color, R1.x, R2, R0;\n"
    439437    "END\n"
     
    443441    "!!ARBfp1.0\n"
    444442    "PARAM c[5] = { program.local[0..3],\n"
    445     "           { 1, 9.9999997e-06 } };\n"
     443    "           { 1, 9.9999997e-006 } };\n"
    446444    "TEMP R0;\n"
    447445    "TEMP R1;\n"
     
    449447    "TEMP R3;\n"
    450448    "TEMP R4;\n"
    451     "MUL R0.xy, fragment.position, c[3];\n"
     449    "MUL R0.xy, fragment.position, c[1];\n"
    452450    "TEX R0, R0, texture[0], 2D;\n"
    453451    "ADD R1.w, -R0, c[4].x;\n"
    454     "MUL R1.xyz, R0, fragment.color.primary.w;\n"
     452    "MUL R1.xyz, fragment.color.primary.w, R0;\n"
    455453    "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n"
    456454    "MAD R1.xyz, -fragment.color.primary.w, R0.w, R2;\n"
    457455    "MUL R3.xyz, fragment.color.primary.w, R1;\n"
    458456    "MAX R1.xyz, fragment.color.primary, c[4].y;\n"
     457    "ADD R2.w, -fragment.color.primary, c[4].x;\n"
    459458    "MUL R4.xyz, fragment.color.primary, R1.w;\n"
    460459    "RCP R1.x, R1.x;\n"
     
    462461    "RCP R1.z, R1.z;\n"
    463462    "MAD R3.xyz, R3, R1, R4;\n"
    464     "ADD R2.w, -fragment.color.primary, c[4].x;\n"
    465463    "MUL R1.xyz, R0, R2.w;\n"
    466464    "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
    467     "ADD R2.w, -fragment.color.primary, c[4].x;\n"
    468465    "MAD R3.xyz, R0, R2.w, R3;\n"
    469466    "MUL R1.w, fragment.color.primary, R0;\n"
     
    473470    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
    474471    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
    475     "ADD R1.xy, fragment.position, c[0];\n"
    476     "MUL R1.xy, R1, c[1];\n"
     472    "ADD R1.xy, fragment.position, c[2];\n"
     473    "MUL R1.xy, R1, c[0];\n"
    477474    "TEX R1, R1, texture[1], 2D;\n"
    478475    "ADD R2, R2, -R0;\n"
    479     "DP4 R1.x, R1, c[2];\n"
     476    "DP4 R1.x, R1, c[3];\n"
    480477    "MAD result.color, R1.x, R2, R0;\n"
    481478    "END\n"
     
    490487    "TEMP R2;\n"
    491488    "TEMP R3;\n"
    492     "MUL R0.xy, fragment.position, c[3];\n"
     489    "MUL R0.xy, fragment.position, c[1];\n"
    493490    "TEX R1, R0, texture[0], 2D;\n"
    494491    "ADD R0.w, -R1, c[4].y;\n"
     
    511508    "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    512509    "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    513     "ADD R0.xy, fragment.position, c[0];\n"
    514     "MUL R0.xy, R0, c[1];\n"
     510    "ADD R0.xy, fragment.position, c[2];\n"
     511    "MUL R0.xy, R0, c[0];\n"
    515512    "TEX R0, R0, texture[1], 2D;\n"
    516513    "ADD R2, R2, -R1;\n"
    517     "DP4 R0.x, R0, c[2];\n"
     514    "DP4 R0.x, R0, c[3];\n"
    518515    "MAD result.color, R0.x, R2, R1;\n"
    519516    "END\n"
     
    523520    "!!ARBfp1.0\n"
    524521    "PARAM c[6] = { program.local[0..3],\n"
    525     "           { 1, 9.9999997e-06, 2, 8 },\n"
    526     "           { 3 } };\n"
     522    "           { 1, 2, 9.9999997e-006, 4 },\n"
     523    "           { 16, 12, 3 } };\n"
    527524    "TEMP R0;\n"
    528525    "TEMP R1;\n"
     
    531528    "TEMP R4;\n"
    532529    "TEMP R5;\n"
    533     "MUL R0.xy, fragment.position, c[3];\n"
     530    "MUL R0.xy, fragment.position, c[1];\n"
    534531    "TEX R0, R0, texture[0], 2D;\n"
    535     "MAX R1.x, R0.w, c[4].y;\n"
    536     "RCP R1.w, R1.x;\n"
    537     "MUL R2.xyz, R0, R1.w;\n"
    538     "MUL R1.xyz, -R2, c[4].w;\n"
    539     "RSQ R2.w, R2.x;\n"
    540     "ADD R4.xyz, R1, c[5].x;\n"
    541     "MAD R1.xyz, -R0, R1.w, c[4].x;\n"
    542     "RSQ R2.z, R2.z;\n"
    543     "RSQ R2.y, R2.y;\n"
    544     "RCP R2.x, R2.w;\n"
    545     "RCP R2.z, R2.z;\n"
    546     "RCP R2.y, R2.y;\n"
    547     "MAD R5.xyz, R2, R0.w, -R0;\n"
    548     "MAD R2.xyz, fragment.color.primary, c[4].z, -fragment.color.primary.w;\n"
    549     "MUL R3.xyz, R1, R2;\n"
    550     "MAD R3.xyz, -R3, R4, fragment.color.primary.w;\n"
    551     "MUL R4.xyz, R5, R2;\n"
    552     "MAD R1.xyz, -R1, R2, fragment.color.primary.w;\n"
    553     "MAD R5.xyz, R0, fragment.color.primary.w, R4;\n"
    554     "MUL R3.xyz, R0, R3;\n"
    555     "MUL R4.xyz, R0, c[4].w;\n"
    556     "ADD R5.xyz, R5, -R3;\n"
    557     "SGE R4.xyz, R4, R0.w;\n"
    558     "MUL R4.xyz, R4, R5;\n"
    559     "ADD R2.xyz, R3, R4;\n"
     532    "MAX R1.x, R0.w, c[4].z;\n"
     533    "RCP R1.x, R1.x;\n"
     534    "MUL R2.xyz, R0, R1.x;\n"
     535    "MAD R1.xyz, R2, c[5].x, -c[5].y;\n"
     536    "MAD R3.xyz, R2, R1, c[5].z;\n"
     537    "MAD R1.xyz, fragment.color.primary, c[4].y, -fragment.color.primary.w;\n"
     538    "MUL R4.xyz, R0.w, R1;\n"
     539    "MUL R5.xyz, R4, R3;\n"
     540    "RSQ R1.w, R2.x;\n"
     541    "RSQ R2.w, R2.z;\n"
     542    "RCP R3.x, R1.w;\n"
     543    "RSQ R1.w, R2.y;\n"
     544    "MUL R5.xyz, R2, R5;\n"
     545    "RCP R3.z, R2.w;\n"
     546    "RCP R3.y, R1.w;\n"
     547    "ADD R3.xyz, -R2, R3;\n"
     548    "MUL R3.xyz, R4, R3;\n"
     549    "ADD R2.xyz, -R2, c[4].x;\n"
     550    "MAD R1.xyz, R1, R2, fragment.color.primary.w;\n"
     551    "MUL R2.xyz, fragment.color.primary, c[4].y;\n"
     552    "MAD R4.xyz, fragment.color.primary.w, R0, R5;\n"
     553    "MAD R3.xyz, fragment.color.primary.w, R0, R3;\n"
     554    "ADD R5.xyz, R3, -R4;\n"
     555    "MUL R3.xyz, R0, c[4].w;\n"
     556    "SGE R3.xyz, R3, R0.w;\n"
     557    "MAD R3.xyz, R3, R5, R4;\n"
     558    "MAD R3.xyz, -R0, R1, R3;\n"
    560559    "MUL R1.xyz, R0, R1;\n"
    561     "MUL R3.xyz, fragment.color.primary, c[4].z;\n"
    562     "ADD R2.xyz, R2, -R1;\n"
    563     "SGE R3.xyz, R3, fragment.color.primary.w;\n"
    564     "MUL R2.xyz, R3, R2;\n"
    565     "ADD R1.xyz, R1, R2;\n"
    566     "ADD R1.w, -R0, c[4].x;\n"
     560    "SGE R2.xyz, R2, fragment.color.primary.w;\n"
     561    "MAD R2.xyz, R2, R3, R1;\n"
     562    "ADD R1.x, -R0.w, c[4];\n"
     563    "MAD R2.xyz, fragment.color.primary, R1.x, R2;\n"
     564    "ADD R1.x, -fragment.color.primary.w, c[4];\n"
     565    "MAD R2.xyz, R0, R1.x, R2;\n"
     566    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
     567    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
     568    "ADD R1.xy, fragment.position, c[2];\n"
     569    "MUL R1.xy, R1, c[0];\n"
     570    "TEX R1, R1, texture[1], 2D;\n"
     571    "ADD R2, R2, -R0;\n"
     572    "DP4 R1.x, R1, c[3];\n"
     573    "MAD result.color, R1.x, R2, R0;\n"
     574    "END\n"
     575    ;
     576
     577static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE =
     578    "!!ARBfp1.0\n"
     579    "PARAM c[5] = { program.local[0..3],\n"
     580    "           { 2 } };\n"
     581    "TEMP R0;\n"
     582    "TEMP R1;\n"
     583    "TEMP R2;\n"
     584    "TEMP R3;\n"
     585    "MUL R0.xy, fragment.position, c[1];\n"
     586    "TEX R0, R0, texture[0], 2D;\n"
     587    "ADD R1.xyz, fragment.color.primary, R0;\n"
     588    "MUL R3.xyz, fragment.color.primary.w, R0;\n"
     589    "MUL R2.xyz, fragment.color.primary, R0.w;\n"
     590    "MIN R2.xyz, R2, R3;\n"
     591    "MAD R2.xyz, -R2, c[4].x, R1;\n"
     592    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
     593    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
     594    "ADD R1.xy, fragment.position, c[2];\n"
     595    "MUL R1.xy, R1, c[0];\n"
     596    "TEX R1, R1, texture[1], 2D;\n"
     597    "ADD R2, R2, -R0;\n"
     598    "DP4 R1.x, R1, c[3];\n"
     599    "MAD result.color, R1.x, R2, R0;\n"
     600    "END\n"
     601    ;
     602
     603static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION =
     604    "!!ARBfp1.0\n"
     605    "PARAM c[5] = { program.local[0..3],\n"
     606    "           { 2, 1 } };\n"
     607    "TEMP R0;\n"
     608    "TEMP R1;\n"
     609    "TEMP R2;\n"
     610    "MUL R0.xy, fragment.position, c[1];\n"
     611    "TEX R0, R0, texture[0], 2D;\n"
     612    "MUL R1.xyz, fragment.color.primary.w, R0;\n"
     613    "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n"
     614    "MUL R1.xyz, fragment.color.primary, R0;\n"
     615    "MAD R1.xyz, -R1, c[4].x, R2;\n"
     616    "ADD R1.w, -R0, c[4].y;\n"
    567617    "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
    568     "ADD R1.w, -fragment.color.primary, c[4].x;\n"
     618    "ADD R1.w, -fragment.color.primary, c[4].y;\n"
    569619    "MAD R2.xyz, R0, R1.w, R1;\n"
    570620    "ADD R1.z, fragment.color.primary.w, R0.w;\n"
    571621    "MAD R2.w, -fragment.color.primary, R0, R1.z;\n"
    572     "ADD R1.xy, fragment.position, c[0];\n"
    573     "MUL R1.xy, R1, c[1];\n"
     622    "ADD R1.xy, fragment.position, c[2];\n"
     623    "MUL R1.xy, R1, c[0];\n"
    574624    "TEX R1, R1, texture[1], 2D;\n"
    575625    "ADD R2, R2, -R0;\n"
    576     "DP4 R1.x, R1, c[2];\n"
     626    "DP4 R1.x, R1, c[3];\n"
    577627    "MAD result.color, R1.x, R2, R0;\n"
    578628    "END\n"
    579629    ;
    580630
    581 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_DIFFERENCE =
    582     "!!ARBfp1.0\n"
    583     "PARAM c[5] = { program.local[0..3],\n"
    584     "           { 2 } };\n"
    585     "TEMP R0;\n"
    586     "TEMP R1;\n"
    587     "TEMP R2;\n"
    588     "TEMP R3;\n"
    589     "MUL R0.xy, fragment.position, c[3];\n"
    590     "TEX R1, R0, texture[0], 2D;\n"
    591     "MUL R2.xyz, R1, fragment.color.primary.w;\n"
    592     "MUL R0.xyz, fragment.color.primary, R1.w;\n"
    593     "MIN R0.xyz, R0, R2;\n"
    594     "ADD R3.xyz, fragment.color.primary, R1;\n"
    595     "MAD R2.xyz, -R0, c[4].x, R3;\n"
    596     "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    597     "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    598     "ADD R0.xy, fragment.position, c[0];\n"
    599     "MUL R0.xy, R0, c[1];\n"
    600     "TEX R0, R0, texture[1], 2D;\n"
    601     "ADD R2, R2, -R1;\n"
    602     "DP4 R0.x, R0, c[2];\n"
    603     "MAD result.color, R0.x, R2, R1;\n"
    604     "END\n"
    605     ;
    606 
    607 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_EXCLUSION =
    608     "!!ARBfp1.0\n"
    609     "PARAM c[5] = { program.local[0..3],\n"
    610     "           { 1, 2 } };\n"
    611     "TEMP R0;\n"
    612     "TEMP R1;\n"
    613     "TEMP R2;\n"
    614     "MUL R0.xy, fragment.position, c[3];\n"
    615     "TEX R1, R0, texture[0], 2D;\n"
    616     "MUL R0.xyz, R1, fragment.color.primary.w;\n"
    617     "MAD R2.xyz, fragment.color.primary, R1.w, R0;\n"
    618     "MUL R0.xyz, fragment.color.primary, R1;\n"
    619     "MAD R0.xyz, -R0, c[4].y, R2;\n"
    620     "ADD R0.w, -R1, c[4].x;\n"
    621     "MAD R0.xyz, fragment.color.primary, R0.w, R0;\n"
    622     "ADD R0.w, -fragment.color.primary, c[4].x;\n"
    623     "MAD R2.xyz, R1, R0.w, R0;\n"
    624     "ADD R0.z, fragment.color.primary.w, R1.w;\n"
    625     "MAD R2.w, -fragment.color.primary, R1, R0.z;\n"
    626     "ADD R0.xy, fragment.position, c[0];\n"
    627     "MUL R0.xy, R0, c[1];\n"
    628     "TEX R0, R0, texture[1], 2D;\n"
    629     "ADD R2, R2, -R1;\n"
    630     "DP4 R0.x, R0, c[2];\n"
    631     "MAD result.color, R0.x, R2, R1;\n"
    632     "END\n"
    633     ;
    634 
    635631static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    636632    "!!ARBfp1.0\n"
    637     "PARAM c[4] = { program.local[0],\n"
    638     "           { 1 },\n"
    639     "           program.local[2..3] };\n"
    640     "TEMP R0;\n"
    641     "TEMP R1;\n"
    642     "TEMP R2;\n"
    643     "MUL R0.xy, fragment.position, c[0];\n"
     633    "PARAM c[4] = { program.local[0..2],\n"
     634    "           { 1 } };\n"
     635    "TEMP R0;\n"
     636    "TEMP R1;\n"
     637    "TEMP R2;\n"
     638    "MUL R0.xy, fragment.position, c[2];\n"
    644639    "TEX R0, R0, texture[0], 2D;\n"
    645     "MUL R1.xyz, R0, c[3].y;\n"
    646     "MUL R2.xyz, R1, fragment.color.primary.w;\n"
    647     "MUL R1.xyz, fragment.color.primary, c[3].x;\n"
    648     "MAD R2.xyz, R1, R0.w, R2;\n"
    649     "MUL R0.xyz, R0, c[2].z;\n"
    650     "ADD R1.w, -R0, c[1].x;\n"
    651     "MUL R1.xyz, fragment.color.primary, c[2].y;\n"
    652     "MAD R1.xyz, R1, R1.w, R2;\n"
    653     "ADD R1.w, -fragment.color.primary, c[1].x;\n"
    654     "MAD result.color.xyz, R0, R1.w, R1;\n"
    655     "ADD R0.y, -R0.w, c[1].x;\n"
     640    "MUL R1.xyz, R0, c[0].y;\n"
     641    "MUL R2.xyz, fragment.color.primary.w, R1;\n"
     642    "MUL R1.xyz, fragment.color.primary, c[0].x;\n"
     643    "MAD R2.xyz, R0.w, R1, R2;\n"
     644    "MUL R0.xyz, R0, c[1].z;\n"
     645    "ADD R1.w, -R0, c[3].x;\n"
     646    "MUL R1.xyz, fragment.color.primary, c[1].y;\n"
     647    "MAD R1.xyz, R1.w, R1, R2;\n"
     648    "ADD R2.x, -fragment.color.primary.w, c[3];\n"
     649    "MAD result.color.xyz, R2.x, R0, R1;\n"
    656650    "MUL R0.x, fragment.color.primary.w, R0.w;\n"
    657     "MUL R0.z, R0.w, R1.w;\n"
    658     "MUL R0.y, fragment.color.primary.w, R0;\n"
    659     "DP3 result.color.w, R0, c[2];\n"
     651    "MUL R0.z, R0.w, R2.x;\n"
     652    "MUL R0.y, fragment.color.primary.w, R1.w;\n"
     653    "DP3 result.color.w, R0, c[1];\n"
    660654    "END\n"
    661655    ;
     
    733727    "MUL R0.xy, fragment.position, c[0];\n"
    734728    "TEX R0, R0, texture[0], 2D;\n"
    735     "MUL R2.xyz, R0, fragment.color.primary.w;\n"
     729    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
    736730    "MUL R1.xyz, fragment.color.primary, R0.w;\n"
    737731    "MIN R1.xyz, R1, R2;\n"
     
    754748    "MUL R0.xy, fragment.position, c[0];\n"
    755749    "TEX R0, R0, texture[0], 2D;\n"
    756     "MUL R2.xyz, R0, fragment.color.primary.w;\n"
     750    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
    757751    "MUL R1.xyz, fragment.color.primary, R0.w;\n"
    758752    "MAX R1.xyz, R1, R2;\n"
     
    769763    "!!ARBfp1.0\n"
    770764    "PARAM c[2] = { program.local[0],\n"
    771     "           { 1, 1e-06 } };\n"
     765    "           { 1, 1e-006 } };\n"
    772766    "TEMP R0;\n"
    773767    "TEMP R1;\n"
     
    783777    "MAD R2.xyz, -fragment.color.primary, R2.x, c[1].x;\n"
    784778    "MAX R2.xyz, R2, c[1].y;\n"
    785     "MUL R0.xyz, R0, fragment.color.primary.w;\n"
     779    "MUL R0.xyz, fragment.color.primary.w, R0;\n"
    786780    "MUL R1.w, fragment.color.primary, R0;\n"
    787781    "RCP R2.x, R2.x;\n"
     
    802796    "!!ARBfp1.0\n"
    803797    "PARAM c[2] = { program.local[0],\n"
    804     "           { 1, 9.9999997e-06 } };\n"
     798    "           { 1, 9.9999997e-006 } };\n"
    805799    "TEMP R0;\n"
    806800    "TEMP R1;\n"
     
    810804    "MUL R0.xy, fragment.position, c[0];\n"
    811805    "TEX R0, R0, texture[0], 2D;\n"
    812     "MUL R1.xyz, R0, fragment.color.primary.w;\n"
     806    "MUL R1.xyz, fragment.color.primary.w, R0;\n"
    813807    "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n"
    814808    "MAD R1.xyz, -fragment.color.primary.w, R0.w, R2;\n"
     
    823817    "MAD R1.xyz, R3, R1, R4;\n"
    824818    "MUL R3.xyz, R0, R2.w;\n"
    825     "ADD R2.w, -fragment.color.primary, c[1].x;\n"
    826819    "MAD R0.xyz, R0, R2.w, R1;\n"
    827820    "MAD R1.xyz, fragment.color.primary, R1.w, R3;\n"
     
    870863    "!!ARBfp1.0\n"
    871864    "PARAM c[3] = { program.local[0],\n"
    872     "           { 1, 9.9999997e-06, 2, 8 },\n"
    873     "           { 3 } };\n"
     865    "           { 1, 2, 9.9999997e-006, 4 },\n"
     866    "           { 16, 12, 3 } };\n"
    874867    "TEMP R0;\n"
    875868    "TEMP R1;\n"
     
    880873    "MUL R0.xy, fragment.position, c[0];\n"
    881874    "TEX R0, R0, texture[0], 2D;\n"
    882     "MAX R1.x, R0.w, c[1].y;\n"
    883     "RCP R1.w, R1.x;\n"
    884     "MUL R2.xyz, R0, R1.w;\n"
    885     "MUL R1.xyz, -R2, c[1].w;\n"
    886     "ADD R4.xyz, R1, c[2].x;\n"
    887     "MAD R1.xyz, -R0, R1.w, c[1].x;\n"
    888     "RSQ R2.w, R2.x;\n"
    889     "RSQ R2.z, R2.z;\n"
    890     "RSQ R2.y, R2.y;\n"
    891     "RCP R2.x, R2.w;\n"
    892     "RCP R2.z, R2.z;\n"
    893     "RCP R2.y, R2.y;\n"
    894     "MAD R5.xyz, R2, R0.w, -R0;\n"
    895     "MAD R2.xyz, fragment.color.primary, c[1].z, -fragment.color.primary.w;\n"
    896     "MUL R3.xyz, R1, R2;\n"
    897     "MAD R3.xyz, -R3, R4, fragment.color.primary.w;\n"
    898     "MUL R4.xyz, R5, R2;\n"
    899     "MAD R1.xyz, -R1, R2, fragment.color.primary.w;\n"
    900     "MAD R5.xyz, R0, fragment.color.primary.w, R4;\n"
    901     "MUL R3.xyz, R0, R3;\n"
    902     "MUL R4.xyz, R0, c[1].w;\n"
    903     "ADD R5.xyz, R5, -R3;\n"
    904     "SGE R4.xyz, R4, R0.w;\n"
    905     "MUL R4.xyz, R4, R5;\n"
    906     "ADD R2.xyz, R3, R4;\n"
     875    "MAX R1.x, R0.w, c[1].z;\n"
     876    "RCP R1.x, R1.x;\n"
     877    "MUL R2.xyz, R0, R1.x;\n"
     878    "MAD R1.xyz, R2, c[2].x, -c[2].y;\n"
     879    "MAD R3.xyz, R2, R1, c[2].z;\n"
     880    "MAD R1.xyz, fragment.color.primary, c[1].y, -fragment.color.primary.w;\n"
     881    "MUL R4.xyz, R0.w, R1;\n"
     882    "MUL R5.xyz, R4, R3;\n"
     883    "RSQ R1.w, R2.x;\n"
     884    "RCP R3.x, R1.w;\n"
     885    "RSQ R2.w, R2.z;\n"
     886    "RSQ R1.w, R2.y;\n"
     887    "MUL R5.xyz, R2, R5;\n"
     888    "RCP R3.z, R2.w;\n"
     889    "RCP R3.y, R1.w;\n"
     890    "ADD R3.xyz, -R2, R3;\n"
     891    "MUL R3.xyz, R4, R3;\n"
     892    "ADD R2.xyz, -R2, c[1].x;\n"
     893    "MAD R1.xyz, R1, R2, fragment.color.primary.w;\n"
     894    "MUL R2.xyz, fragment.color.primary, c[1].y;\n"
     895    "MAD R4.xyz, fragment.color.primary.w, R0, R5;\n"
     896    "MAD R3.xyz, fragment.color.primary.w, R0, R3;\n"
     897    "ADD R5.xyz, R3, -R4;\n"
     898    "MUL R3.xyz, R0, c[1].w;\n"
     899    "SGE R3.xyz, R3, R0.w;\n"
     900    "MAD R3.xyz, R3, R5, R4;\n"
     901    "MAD R3.xyz, -R0, R1, R3;\n"
    907902    "MUL R1.xyz, R0, R1;\n"
    908     "MUL R3.xyz, fragment.color.primary, c[1].z;\n"
    909     "ADD R2.xyz, R2, -R1;\n"
    910     "SGE R3.xyz, R3, fragment.color.primary.w;\n"
    911     "MUL R2.xyz, R3, R2;\n"
    912     "ADD R1.xyz, R1, R2;\n"
    913     "ADD R1.w, -R0, c[1].x;\n"
    914     "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
    915     "ADD R1.w, fragment.color.primary, R0;\n"
    916     "ADD R2.x, -fragment.color.primary.w, c[1];\n"
    917     "MAD result.color.xyz, R0, R2.x, R1;\n"
    918     "MAD result.color.w, -fragment.color.primary, R0, R1;\n"
     903    "SGE R2.xyz, R2, fragment.color.primary.w;\n"
     904    "MAD R2.xyz, R2, R3, R1;\n"
     905    "ADD R1.x, -R0.w, c[1];\n"
     906    "MAD R2.xyz, fragment.color.primary, R1.x, R2;\n"
     907    "ADD R1.x, fragment.color.primary.w, R0.w;\n"
     908    "ADD R1.y, -fragment.color.primary.w, c[1].x;\n"
     909    "MAD result.color.xyz, R0, R1.y, R2;\n"
     910    "MAD result.color.w, -fragment.color.primary, R0, R1.x;\n"
    919911    "END\n"
    920912    ;
     
    929921    "MUL R0.xy, fragment.position, c[0];\n"
    930922    "TEX R0, R0, texture[0], 2D;\n"
    931     "MUL R2.xyz, R0, fragment.color.primary.w;\n"
     923    "MUL R2.xyz, fragment.color.primary.w, R0;\n"
    932924    "MUL R1.xyz, fragment.color.primary, R0.w;\n"
    933925    "ADD R1.w, fragment.color.primary, R0;\n"
     
    942934    "!!ARBfp1.0\n"
    943935    "PARAM c[2] = { program.local[0],\n"
    944     "           { 1, 2 } };\n"
     936    "           { 2, 1 } };\n"
    945937    "TEMP R0;\n"
    946938    "TEMP R1;\n"
     
    948940    "MUL R0.xy, fragment.position, c[0];\n"
    949941    "TEX R0, R0, texture[0], 2D;\n"
    950     "MUL R1.xyz, R0, fragment.color.primary.w;\n"
     942    "MUL R1.xyz, fragment.color.primary.w, R0;\n"
    951943    "MAD R2.xyz, fragment.color.primary, R0.w, R1;\n"
    952944    "MUL R1.xyz, fragment.color.primary, R0;\n"
    953     "MAD R1.xyz, -R1, c[1].y, R2;\n"
    954     "ADD R1.w, -R0, c[1].x;\n"
     945    "MAD R1.xyz, -R1, c[1].x, R2;\n"
     946    "ADD R1.w, -R0, c[1].y;\n"
    955947    "MAD R1.xyz, fragment.color.primary, R1.w, R1;\n"
    956948    "ADD R1.w, fragment.color.primary, R0;\n"
    957     "ADD R2.x, -fragment.color.primary.w, c[1];\n"
     949    "ADD R2.x, -fragment.color.primary.w, c[1].y;\n"
    958950    "MAD result.color.xyz, R0, R2.x, R1;\n"
    959951    "MAD result.color.w, -fragment.color.primary, R0, R1;\n"
     
    965957    "PARAM c[3] = { program.local[0..2] };\n"
    966958    "TEMP R0;\n"
    967     "ADD R0.xy, fragment.position, c[0];\n"
    968     "MUL R0.xy, R0, c[1];\n"
     959    "ADD R0.xy, fragment.position, c[1];\n"
     960    "MUL R0.xy, R0, c[0];\n"
    969961    "TEX R0, R0, texture[0], 2D;\n"
    970962    "DP4 R0.x, R0, c[2];\n"
     
    975967static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_SOLID_COMPOSITION_MODE_BLEND_MODE_NOMASK =
    976968    "!!ARBfp1.0\n"
    977     "PARAM c[1] = { program.local[0] };\n"
    978969    "MOV result.color, fragment.color.primary;\n"
    979970    "END\n"
     
    982973static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    983974    "!!ARBfp1.0\n"
    984     "PARAM c[12] = { program.local[0..6],\n"
    985     "           { 2, 4, 1 },\n"
    986     "           program.local[8..11] };\n"
    987     "TEMP R0;\n"
    988     "TEMP R1;\n"
    989     "TEMP R2;\n"
    990     "TEMP R3;\n"
    991     "MUL R0.xyz, fragment.position.y, c[4];\n"
    992     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    993     "ADD R0.xyz, R0, c[5];\n"
     975    "PARAM c[12] = { program.local[0..10],\n"
     976    "           { 2, 4, 1 } };\n"
     977    "TEMP R0;\n"
     978    "TEMP R1;\n"
     979    "TEMP R2;\n"
     980    "TEMP R3;\n"
     981    "MUL R0.xyz, fragment.position.y, c[3];\n"
     982    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     983    "ADD R0.xyz, R0, c[4];\n"
    994984    "RCP R0.z, R0.z;\n"
    995985    "MUL R0.xy, R0, R0.z;\n"
    996986    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    997987    "ADD R0.z, R0, R0.w;\n"
    998     "MUL R0.xy, R0, c[6];\n"
     988    "MUL R0.xy, R0, c[0];\n"
    999989    "ADD R0.x, R0, R0.y;\n"
    1000     "MUL R0.z, c[8].x, -R0;\n"
    1001     "MUL R0.y, R0.z, c[7];\n"
    1002     "MUL R0.x, R0, c[7];\n"
    1003     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1004     "RSQ R0.z, R0.y;\n"
    1005     "RCP R0.z, R0.z;\n"
    1006     "ADD R0.x, -R0, R0.z;\n"
    1007     "MUL R0.zw, fragment.position.xyxy, c[9].xyxy;\n"
    1008     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1009     "MOV R0.y, c[7].x;\n"
    1010     "MUL R0.y, c[8].x, R0;\n"
    1011     "RCP R0.y, R0.y;\n"
    1012     "MUL R0.x, R0, R0.y;\n"
    1013     "TEX R0, R0, texture[2], 1D;\n"
    1014     "MUL R2.xyz, R1, c[11].y;\n"
    1015     "MUL R3.xyz, R2, R0.w;\n"
    1016     "MUL R2.xyz, R0, c[11].x;\n"
    1017     "MAD R2.xyz, R2, R1.w, R3;\n"
    1018     "ADD R3.xy, fragment.position, c[0];\n"
    1019     "ADD R2.w, -R1, c[7].z;\n"
    1020     "MUL R0.xyz, R0, c[10].y;\n"
    1021     "MAD R2.xyz, R0, R2.w, R2;\n"
    1022     "MUL R0.xyz, R1, c[10].z;\n"
    1023     "ADD R3.z, -R0.w, c[7];\n"
    1024     "MAD R2.xyz, R0, R3.z, R2;\n"
    1025     "MUL R0.y, R0.w, R2.w;\n"
    1026     "MUL R0.x, R0.w, R1.w;\n"
    1027     "MUL R0.z, R1.w, R3;\n"
    1028     "DP3 R2.w, R0, c[10];\n"
    1029     "MUL R3.xy, R3, c[1];\n"
    1030     "TEX R0, R3, texture[1], 2D;\n"
    1031     "ADD R2, R2, -R1;\n"
    1032     "DP4 R0.x, R0, c[2];\n"
    1033     "MAD result.color, R0.x, R2, R1;\n"
     990    "MUL R0.z, -R0, c[1].x;\n"
     991    "MUL R0.y, R0.x, c[11].x;\n"
     992    "MUL R0.z, R0, c[11].y;\n"
     993    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     994    "RSQ R0.x, R0.x;\n"
     995    "RCP R0.z, R0.x;\n"
     996    "ADD R1.x, -R0.y, R0.z;\n"
     997    "MOV R0.x, c[11];\n"
     998    "MUL R0.z, R0.x, c[1].x;\n"
     999    "RCP R1.y, R0.z;\n"
     1000    "MUL R0.xy, fragment.position, c[8];\n"
     1001    "TEX R0, R0, texture[0], 2D;\n"
     1002    "MUL R1.x, R1, R1.y;\n"
     1003    "TEX R1, R1, texture[2], 1D;\n"
     1004    "MUL R2.xyz, R0, c[5].y;\n"
     1005    "MUL R3.xyz, R1.w, R2;\n"
     1006    "MUL R2.xyz, R1, c[5].x;\n"
     1007    "MAD R2.xyz, R0.w, R2, R3;\n"
     1008    "ADD R3.xy, fragment.position, c[9];\n"
     1009    "ADD R2.w, -R0, c[11].z;\n"
     1010    "MUL R1.xyz, R1, c[6].y;\n"
     1011    "MAD R2.xyz, R2.w, R1, R2;\n"
     1012    "MUL R1.xyz, R0, c[6].z;\n"
     1013    "ADD R3.z, -R1.w, c[11];\n"
     1014    "MAD R2.xyz, R3.z, R1, R2;\n"
     1015    "MUL R1.y, R1.w, R2.w;\n"
     1016    "MUL R1.x, R1.w, R0.w;\n"
     1017    "MUL R1.z, R0.w, R3;\n"
     1018    "DP3 R2.w, R1, c[6];\n"
     1019    "MUL R3.xy, R3, c[7];\n"
     1020    "TEX R1, R3, texture[1], 2D;\n"
     1021    "ADD R2, R2, -R0;\n"
     1022    "DP4 R1.x, R1, c[10];\n"
     1023    "MAD result.color, R1.x, R2, R0;\n"
    10341024    "END\n"
    10351025    ;
     
    10371027static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY =
    10381028    "!!ARBfp1.0\n"
    1039     "PARAM c[10] = { program.local[0..6],\n"
    1040     "           { 2, 4, 1 },\n"
    1041     "           program.local[8..9] };\n"
    1042     "TEMP R0;\n"
    1043     "TEMP R1;\n"
    1044     "TEMP R2;\n"
    1045     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1046     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1047     "ADD R0.xyz, R0, c[5];\n"
     1029    "PARAM c[10] = { program.local[0..8],\n"
     1030    "           { 2, 4, 1 } };\n"
     1031    "TEMP R0;\n"
     1032    "TEMP R1;\n"
     1033    "TEMP R2;\n"
     1034    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1035    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1036    "ADD R0.xyz, R0, c[4];\n"
    10481037    "RCP R0.z, R0.z;\n"
    10491038    "MUL R0.xy, R0, R0.z;\n"
    10501039    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1051     "MUL R0.xy, R0, c[6];\n"
    10521040    "ADD R0.z, R0, R0.w;\n"
     1041    "MUL R0.xy, R0, c[0];\n"
    10531042    "ADD R0.x, R0, R0.y;\n"
    1054     "MUL R0.z, c[8].x, -R0;\n"
    1055     "MUL R0.y, R0.z, c[7];\n"
    1056     "MUL R0.x, R0, c[7];\n"
    1057     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1058     "RSQ R0.y, R0.y;\n"
    1059     "RCP R0.z, R0.y;\n"
    1060     "ADD R0.x, -R0, R0.z;\n"
    1061     "MUL R0.zw, fragment.position.xyxy, c[9].xyxy;\n"
    1062     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1063     "MOV R0.y, c[7].x;\n"
    1064     "MUL R0.y, c[8].x, R0;\n"
    1065     "RCP R0.y, R0.y;\n"
    1066     "MUL R0.x, R0, R0.y;\n"
    1067     "TEX R0, R0, texture[2], 1D;\n"
    1068     "ADD R2.x, -R1.w, c[7].z;\n"
    1069     "MUL R2.xyz, R0, R2.x;\n"
    1070     "MAD R0.xyz, R0, R1, R2;\n"
    1071     "ADD R2.x, -R0.w, c[7].z;\n"
    1072     "MAD R2.xyz, R1, R2.x, R0;\n"
    1073     "ADD R0.z, R0.w, R1.w;\n"
    1074     "MAD R2.w, -R0, R1, R0.z;\n"
    1075     "ADD R0.xy, fragment.position, c[0];\n"
    1076     "MUL R0.xy, R0, c[1];\n"
    1077     "TEX R0, R0, texture[1], 2D;\n"
    1078     "ADD R2, R2, -R1;\n"
    1079     "DP4 R0.x, R0, c[2];\n"
    1080     "MAD result.color, R0.x, R2, R1;\n"
     1043    "MUL R0.z, -R0, c[1].x;\n"
     1044    "MUL R0.y, R0.x, c[9].x;\n"
     1045    "MUL R0.z, R0, c[9].y;\n"
     1046    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1047    "RSQ R0.x, R0.x;\n"
     1048    "RCP R0.z, R0.x;\n"
     1049    "ADD R1.x, -R0.y, R0.z;\n"
     1050    "MOV R0.x, c[9];\n"
     1051    "MUL R0.z, R0.x, c[1].x;\n"
     1052    "RCP R1.y, R0.z;\n"
     1053    "MUL R0.xy, fragment.position, c[6];\n"
     1054    "TEX R0, R0, texture[0], 2D;\n"
     1055    "MUL R1.x, R1, R1.y;\n"
     1056    "TEX R1, R1, texture[2], 1D;\n"
     1057    "ADD R2.x, -R0.w, c[9].z;\n"
     1058    "MUL R2.xyz, R1, R2.x;\n"
     1059    "MAD R1.xyz, R1, R0, R2;\n"
     1060    "ADD R2.x, -R1.w, c[9].z;\n"
     1061    "MAD R2.xyz, R0, R2.x, R1;\n"
     1062    "ADD R1.z, R1.w, R0.w;\n"
     1063    "MAD R2.w, -R1, R0, R1.z;\n"
     1064    "ADD R1.xy, fragment.position, c[7];\n"
     1065    "MUL R1.xy, R1, c[5];\n"
     1066    "TEX R1, R1, texture[1], 2D;\n"
     1067    "ADD R2, R2, -R0;\n"
     1068    "DP4 R1.x, R1, c[8];\n"
     1069    "MAD result.color, R1.x, R2, R0;\n"
    10811070    "END\n"
    10821071    ;
     
    10841073static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN =
    10851074    "!!ARBfp1.0\n"
    1086     "PARAM c[10] = { program.local[0..6],\n"
    1087     "           { 2, 4 },\n"
    1088     "           program.local[8..9] };\n"
    1089     "TEMP R0;\n"
    1090     "TEMP R1;\n"
    1091     "TEMP R2;\n"
    1092     "TEMP R3;\n"
    1093     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1094     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1095     "ADD R0.xyz, R0, c[5];\n"
     1075    "PARAM c[10] = { program.local[0..8],\n"
     1076    "           { 2, 4 } };\n"
     1077    "TEMP R0;\n"
     1078    "TEMP R1;\n"
     1079    "TEMP R2;\n"
     1080    "TEMP R3;\n"
     1081    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1082    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1083    "ADD R0.xyz, R0, c[4];\n"
    10961084    "RCP R0.z, R0.z;\n"
    10971085    "MUL R0.xy, R0, R0.z;\n"
    10981086    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1099     "MUL R0.xy, R0, c[6];\n"
    11001087    "ADD R0.z, R0, R0.w;\n"
     1088    "MUL R0.xy, R0, c[0];\n"
    11011089    "ADD R0.x, R0, R0.y;\n"
    1102     "MUL R0.z, c[8].x, -R0;\n"
    1103     "MUL R0.y, R0.z, c[7];\n"
    1104     "MUL R0.x, R0, c[7];\n"
    1105     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1106     "MOV R0.z, c[7].x;\n"
    1107     "RSQ R0.y, R0.y;\n"
    1108     "RCP R0.y, R0.y;\n"
    1109     "MUL R0.z, c[8].x, R0;\n"
    1110     "MUL R1.xy, fragment.position, c[9];\n"
    1111     "ADD R3.xy, fragment.position, c[0];\n"
     1090    "MUL R0.y, R0.x, c[9].x;\n"
     1091    "MOV R0.x, c[9];\n"
     1092    "MUL R0.z, -R0, c[1].x;\n"
     1093    "MUL R0.z, R0, c[9].y;\n"
     1094    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1095    "ADD R3.xy, fragment.position, c[7];\n"
     1096    "MUL R0.w, R0.x, c[1].x;\n"
     1097    "RSQ R0.z, R0.z;\n"
     1098    "RCP R0.x, R0.z;\n"
     1099    "RCP R0.z, R0.w;\n"
     1100    "ADD R0.x, -R0.y, R0;\n"
     1101    "MUL R0.z, R0.x, R0;\n"
     1102    "TEX R1, R0.z, texture[2], 1D;\n"
     1103    "MUL R0.xy, fragment.position, c[6];\n"
     1104    "TEX R0, R0, texture[0], 2D;\n"
     1105    "ADD R2, R1, R0;\n"
     1106    "MAD R2, -R1, R0, R2;\n"
     1107    "MUL R3.xy, R3, c[5];\n"
     1108    "TEX R1, R3, texture[1], 2D;\n"
     1109    "ADD R2, R2, -R0;\n"
     1110    "DP4 R1.x, R1, c[8];\n"
     1111    "MAD result.color, R1.x, R2, R0;\n"
     1112    "END\n"
     1113    ;
     1114
     1115static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY =
     1116    "!!ARBfp1.0\n"
     1117    "PARAM c[10] = { program.local[0..8],\n"
     1118    "           { 2, 4, 1 } };\n"
     1119    "TEMP R0;\n"
     1120    "TEMP R1;\n"
     1121    "TEMP R2;\n"
     1122    "TEMP R3;\n"
     1123    "TEMP R4;\n"
     1124    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1125    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1126    "ADD R0.xyz, R0, c[4];\n"
     1127    "RCP R0.z, R0.z;\n"
     1128    "MUL R0.xy, R0, R0.z;\n"
     1129    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1130    "ADD R0.z, R0, R0.w;\n"
     1131    "MUL R0.xy, R0, c[0];\n"
     1132    "ADD R0.x, R0, R0.y;\n"
     1133    "MUL R0.y, R0.x, c[9].x;\n"
     1134    "MOV R0.x, c[9];\n"
     1135    "MUL R0.z, -R0, c[1].x;\n"
     1136    "MUL R0.z, R0, c[9].y;\n"
     1137    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1138    "MUL R1.xy, fragment.position, c[6];\n"
    11121139    "TEX R1, R1, texture[0], 2D;\n"
    1113     "ADD R0.x, -R0, R0.y;\n"
    1114     "RCP R0.z, R0.z;\n"
     1140    "MUL R0.w, R0.x, c[1].x;\n"
     1141    "RSQ R0.z, R0.z;\n"
     1142    "RCP R0.x, R0.z;\n"
     1143    "ADD R2.w, -R1, c[9].z;\n"
     1144    "RCP R0.z, R0.w;\n"
     1145    "ADD R0.x, -R0.y, R0;\n"
    11151146    "MUL R0.x, R0, R0.z;\n"
    11161147    "TEX R0, R0, texture[2], 1D;\n"
    1117     "ADD R2, R0, R1;\n"
    1118     "MAD R2, -R0, R1, R2;\n"
    1119     "MUL R3.xy, R3, c[1];\n"
    1120     "TEX R0, R3, texture[1], 2D;\n"
    1121     "ADD R2, R2, -R1;\n"
    1122     "DP4 R0.x, R0, c[2];\n"
    1123     "MAD result.color, R0.x, R2, R1;\n"
    1124     "END\n"
    1125     ;
    1126 
    1127 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY =
    1128     "!!ARBfp1.0\n"
    1129     "PARAM c[10] = { program.local[0..6],\n"
    1130     "           { 2, 4, 1 },\n"
    1131     "           program.local[8..9] };\n"
    1132     "TEMP R0;\n"
    1133     "TEMP R1;\n"
    1134     "TEMP R2;\n"
    1135     "TEMP R3;\n"
    1136     "TEMP R4;\n"
    1137     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1138     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1139     "ADD R0.xyz, R0, c[5];\n"
    1140     "RCP R0.z, R0.z;\n"
    1141     "MUL R0.xy, R0, R0.z;\n"
    1142     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1143     "MUL R0.xy, R0, c[6];\n"
    1144     "ADD R0.z, R0, R0.w;\n"
    1145     "ADD R0.x, R0, R0.y;\n"
    1146     "MUL R0.z, c[8].x, -R0;\n"
    1147     "MUL R0.y, R0.z, c[7];\n"
    1148     "MUL R0.x, R0, c[7];\n"
    1149     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1150     "MOV R0.z, c[7].x;\n"
    1151     "RSQ R0.y, R0.y;\n"
    1152     "RCP R0.y, R0.y;\n"
    1153     "MUL R0.z, c[8].x, R0;\n"
    1154     "MUL R1.xy, fragment.position, c[9];\n"
    1155     "TEX R1, R1, texture[0], 2D;\n"
    1156     "ADD R0.x, -R0, R0.y;\n"
    1157     "RCP R0.z, R0.z;\n"
    1158     "MUL R0.x, R0, R0.z;\n"
    1159     "TEX R0, R0, texture[2], 1D;\n"
    1160     "ADD R2.w, -R1, c[7].z;\n"
    11611148    "ADD R3.xyz, R0.w, -R0;\n"
    11621149    "ADD R2.xyz, R1.w, -R1;\n"
    11631150    "MUL R2.xyz, R2, R3;\n"
    1164     "MUL R2.xyz, R2, c[7].x;\n"
     1151    "MUL R2.xyz, R2, c[9].x;\n"
    11651152    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    11661153    "MUL R4.xyz, R0, R2.w;\n"
    11671154    "MUL R3.xyz, R0, R1;\n"
    11681155    "MAD R0.xyz, R0, R2.w, R2;\n"
    1169     "ADD R2.x, -R0.w, c[7].z;\n"
    1170     "MAD R3.xyz, R3, c[7].x, R4;\n"
     1156    "ADD R2.x, -R0.w, c[9].z;\n"
     1157    "MAD R3.xyz, R3, c[9].x, R4;\n"
    11711158    "MAD R3.xyz, R1, R2.x, R3;\n"
    11721159    "MAD R0.xyz, R1, R2.x, R0;\n"
    1173     "MUL R2.xyz, R1, c[7].x;\n"
     1160    "MUL R2.xyz, R1, c[9].x;\n"
    11741161    "ADD R0.xyz, R0, -R3;\n"
    11751162    "SGE R2.xyz, R2, R1.w;\n"
     
    11771164    "ADD R0.z, R0.w, R1.w;\n"
    11781165    "MAD R2.w, -R0, R1, R0.z;\n"
    1179     "ADD R0.xy, fragment.position, c[0];\n"
    1180     "MUL R0.xy, R0, c[1];\n"
     1166    "ADD R0.xy, fragment.position, c[7];\n"
     1167    "MUL R0.xy, R0, c[5];\n"
    11811168    "TEX R0, R0, texture[1], 2D;\n"
    11821169    "ADD R2, R2, -R1;\n"
    1183     "DP4 R0.x, R0, c[2];\n"
     1170    "DP4 R0.x, R0, c[8];\n"
    11841171    "MAD result.color, R0.x, R2, R1;\n"
    11851172    "END\n"
     
    11881175static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN =
    11891176    "!!ARBfp1.0\n"
    1190     "PARAM c[10] = { program.local[0..6],\n"
    1191     "           { 2, 4, 1 },\n"
    1192     "           program.local[8..9] };\n"
    1193     "TEMP R0;\n"
    1194     "TEMP R1;\n"
    1195     "TEMP R2;\n"
    1196     "TEMP R3;\n"
    1197     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1198     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1199     "ADD R0.xyz, R0, c[5];\n"
     1177    "PARAM c[10] = { program.local[0..8],\n"
     1178    "           { 2, 4, 1 } };\n"
     1179    "TEMP R0;\n"
     1180    "TEMP R1;\n"
     1181    "TEMP R2;\n"
     1182    "TEMP R3;\n"
     1183    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1184    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1185    "ADD R0.xyz, R0, c[4];\n"
    12001186    "RCP R0.z, R0.z;\n"
    12011187    "MUL R0.xy, R0, R0.z;\n"
    12021188    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1203     "MUL R0.xy, R0, c[6];\n"
    12041189    "ADD R0.z, R0, R0.w;\n"
     1190    "MUL R0.xy, R0, c[0];\n"
    12051191    "ADD R0.x, R0, R0.y;\n"
    1206     "MUL R0.z, c[8].x, -R0;\n"
    1207     "MUL R0.y, R0.z, c[7];\n"
    1208     "MUL R0.x, R0, c[7];\n"
    1209     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1210     "MOV R0.z, c[7].x;\n"
    1211     "RSQ R0.y, R0.y;\n"
    1212     "RCP R0.y, R0.y;\n"
    1213     "MUL R0.z, c[8].x, R0;\n"
    1214     "MUL R1.xy, fragment.position, c[9];\n"
    1215     "TEX R1, R1, texture[0], 2D;\n"
    1216     "ADD R0.x, -R0, R0.y;\n"
    1217     "RCP R0.z, R0.z;\n"
     1192    "MUL R0.z, -R0, c[1].x;\n"
     1193    "MUL R0.y, R0.x, c[9].x;\n"
     1194    "MUL R0.z, R0, c[9].y;\n"
     1195    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1196    "RSQ R0.z, R0.x;\n"
     1197    "MOV R0.x, c[9];\n"
     1198    "MUL R0.x, R0, c[1];\n"
     1199    "RCP R0.z, R0.z;\n"
     1200    "ADD R0.z, -R0.y, R0;\n"
     1201    "RCP R0.w, R0.x;\n"
     1202    "MUL R1.x, R0.z, R0.w;\n"
     1203    "MUL R0.xy, fragment.position, c[6];\n"
     1204    "TEX R0, R0, texture[0], 2D;\n"
     1205    "TEX R1, R1, texture[2], 1D;\n"
     1206    "MUL R3.xyz, R1.w, R0;\n"
     1207    "MUL R2.xyz, R1, R0.w;\n"
     1208    "MIN R2.xyz, R2, R3;\n"
     1209    "ADD R2.w, -R0, c[9].z;\n"
     1210    "MAD R1.xyz, R1, R2.w, R2;\n"
     1211    "ADD R2.x, -R1.w, c[9].z;\n"
     1212    "MAD R2.xyz, R0, R2.x, R1;\n"
     1213    "ADD R1.z, R1.w, R0.w;\n"
     1214    "MAD R2.w, -R1, R0, R1.z;\n"
     1215    "ADD R1.xy, fragment.position, c[7];\n"
     1216    "MUL R1.xy, R1, c[5];\n"
     1217    "TEX R1, R1, texture[1], 2D;\n"
     1218    "ADD R2, R2, -R0;\n"
     1219    "DP4 R1.x, R1, c[8];\n"
     1220    "MAD result.color, R1.x, R2, R0;\n"
     1221    "END\n"
     1222    ;
     1223
     1224static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN =
     1225    "!!ARBfp1.0\n"
     1226    "PARAM c[10] = { program.local[0..8],\n"
     1227    "           { 2, 4, 1 } };\n"
     1228    "TEMP R0;\n"
     1229    "TEMP R1;\n"
     1230    "TEMP R2;\n"
     1231    "TEMP R3;\n"
     1232    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1233    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1234    "ADD R0.xyz, R0, c[4];\n"
     1235    "RCP R0.z, R0.z;\n"
     1236    "MUL R0.xy, R0, R0.z;\n"
     1237    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1238    "ADD R0.z, R0, R0.w;\n"
     1239    "MUL R0.xy, R0, c[0];\n"
     1240    "ADD R0.x, R0, R0.y;\n"
     1241    "MUL R0.z, -R0, c[1].x;\n"
     1242    "MUL R0.y, R0.x, c[9].x;\n"
     1243    "MUL R0.z, R0, c[9].y;\n"
     1244    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1245    "RSQ R0.z, R0.x;\n"
     1246    "MOV R0.x, c[9];\n"
     1247    "MUL R0.x, R0, c[1];\n"
     1248    "RCP R0.z, R0.z;\n"
     1249    "ADD R0.z, -R0.y, R0;\n"
     1250    "RCP R0.w, R0.x;\n"
     1251    "MUL R1.x, R0.z, R0.w;\n"
     1252    "MUL R0.xy, fragment.position, c[6];\n"
     1253    "TEX R0, R0, texture[0], 2D;\n"
     1254    "TEX R1, R1, texture[2], 1D;\n"
     1255    "MUL R3.xyz, R1.w, R0;\n"
     1256    "MUL R2.xyz, R1, R0.w;\n"
     1257    "MAX R2.xyz, R2, R3;\n"
     1258    "ADD R2.w, -R0, c[9].z;\n"
     1259    "MAD R1.xyz, R1, R2.w, R2;\n"
     1260    "ADD R2.x, -R1.w, c[9].z;\n"
     1261    "MAD R2.xyz, R0, R2.x, R1;\n"
     1262    "ADD R1.z, R1.w, R0.w;\n"
     1263    "MAD R2.w, -R1, R0, R1.z;\n"
     1264    "ADD R1.xy, fragment.position, c[7];\n"
     1265    "MUL R1.xy, R1, c[5];\n"
     1266    "TEX R1, R1, texture[1], 2D;\n"
     1267    "ADD R2, R2, -R0;\n"
     1268    "DP4 R1.x, R1, c[8];\n"
     1269    "MAD result.color, R1.x, R2, R0;\n"
     1270    "END\n"
     1271    ;
     1272
     1273static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE =
     1274    "!!ARBfp1.0\n"
     1275    "PARAM c[10] = { program.local[0..8],\n"
     1276    "           { 2, 4, 1, 1e-006 } };\n"
     1277    "TEMP R0;\n"
     1278    "TEMP R1;\n"
     1279    "TEMP R2;\n"
     1280    "TEMP R3;\n"
     1281    "TEMP R4;\n"
     1282    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1283    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1284    "ADD R0.xyz, R0, c[4];\n"
     1285    "RCP R0.z, R0.z;\n"
     1286    "MUL R0.xy, R0, R0.z;\n"
     1287    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1288    "ADD R0.z, R0, R0.w;\n"
     1289    "MUL R0.xy, R0, c[0];\n"
     1290    "ADD R0.x, R0, R0.y;\n"
     1291    "MUL R0.y, R0.x, c[9].x;\n"
     1292    "MOV R0.x, c[9];\n"
     1293    "MUL R0.z, -R0, c[1].x;\n"
     1294    "MUL R0.z, R0, c[9].y;\n"
     1295    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1296    "MUL R0.w, R0.x, c[1].x;\n"
     1297    "RSQ R0.z, R0.z;\n"
     1298    "RCP R0.x, R0.z;\n"
     1299    "RCP R0.z, R0.w;\n"
     1300    "ADD R0.x, -R0.y, R0;\n"
    12181301    "MUL R0.x, R0, R0.z;\n"
    12191302    "TEX R0, R0, texture[2], 1D;\n"
    1220     "MUL R3.xyz, R1, R0.w;\n"
    1221     "MUL R2.xyz, R0, R1.w;\n"
    1222     "MIN R2.xyz, R2, R3;\n"
    1223     "ADD R2.w, -R1, c[7].z;\n"
    1224     "MAD R0.xyz, R0, R2.w, R2;\n"
    1225     "ADD R2.x, -R0.w, c[7].z;\n"
    1226     "MAD R2.xyz, R1, R2.x, R0;\n"
    1227     "ADD R0.z, R0.w, R1.w;\n"
    1228     "MAD R2.w, -R0, R1, R0.z;\n"
    1229     "ADD R0.xy, fragment.position, c[0];\n"
    1230     "MUL R0.xy, R0, c[1];\n"
    1231     "TEX R0, R0, texture[1], 2D;\n"
    1232     "ADD R2, R2, -R1;\n"
    1233     "DP4 R0.x, R0, c[2];\n"
    1234     "MAD result.color, R0.x, R2, R1;\n"
    1235     "END\n"
    1236     ;
    1237 
    1238 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN =
    1239     "!!ARBfp1.0\n"
    1240     "PARAM c[10] = { program.local[0..6],\n"
    1241     "           { 2, 4, 1 },\n"
    1242     "           program.local[8..9] };\n"
    1243     "TEMP R0;\n"
    1244     "TEMP R1;\n"
    1245     "TEMP R2;\n"
    1246     "TEMP R3;\n"
    1247     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1248     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1249     "ADD R0.xyz, R0, c[5];\n"
    1250     "RCP R0.z, R0.z;\n"
    1251     "MUL R0.xy, R0, R0.z;\n"
    1252     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1253     "MUL R0.xy, R0, c[6];\n"
    1254     "ADD R0.z, R0, R0.w;\n"
    1255     "ADD R0.x, R0, R0.y;\n"
    1256     "MUL R0.z, c[8].x, -R0;\n"
    1257     "MUL R0.y, R0.z, c[7];\n"
    1258     "MUL R0.x, R0, c[7];\n"
    1259     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1260     "MOV R0.z, c[7].x;\n"
    1261     "RSQ R0.y, R0.y;\n"
    1262     "RCP R0.y, R0.y;\n"
    1263     "MUL R0.z, c[8].x, R0;\n"
    1264     "MUL R1.xy, fragment.position, c[9];\n"
     1303    "MAX R1.x, R0.w, c[9].w;\n"
     1304    "RCP R1.x, R1.x;\n"
     1305    "MAD R1.xyz, -R0, R1.x, c[9].z;\n"
     1306    "MAX R2.xyz, R1, c[9].w;\n"
     1307    "MUL R1.xy, fragment.position, c[6];\n"
    12651308    "TEX R1, R1, texture[0], 2D;\n"
    1266     "ADD R0.x, -R0, R0.y;\n"
    1267     "RCP R0.z, R0.z;\n"
    1268     "MUL R0.x, R0, R0.z;\n"
    1269     "TEX R0, R0, texture[2], 1D;\n"
    1270     "MUL R3.xyz, R1, R0.w;\n"
    1271     "MUL R2.xyz, R0, R1.w;\n"
    1272     "MAX R2.xyz, R2, R3;\n"
    1273     "ADD R2.w, -R1, c[7].z;\n"
    1274     "MAD R0.xyz, R0, R2.w, R2;\n"
    1275     "ADD R2.x, -R0.w, c[7].z;\n"
    1276     "MAD R2.xyz, R1, R2.x, R0;\n"
    1277     "ADD R0.z, R0.w, R1.w;\n"
    1278     "MAD R2.w, -R0, R1, R0.z;\n"
    1279     "ADD R0.xy, fragment.position, c[0];\n"
    1280     "MUL R0.xy, R0, c[1];\n"
    1281     "TEX R0, R0, texture[1], 2D;\n"
    1282     "ADD R2, R2, -R1;\n"
    1283     "DP4 R0.x, R0, c[2];\n"
    1284     "MAD result.color, R0.x, R2, R1;\n"
    1285     "END\n"
    1286     ;
    1287 
    1288 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE =
    1289     "!!ARBfp1.0\n"
    1290     "PARAM c[10] = { program.local[0..6],\n"
    1291     "           { 2, 4, 1, 1e-06 },\n"
    1292     "           program.local[8..9] };\n"
    1293     "TEMP R0;\n"
    1294     "TEMP R1;\n"
    1295     "TEMP R2;\n"
    1296     "TEMP R3;\n"
    1297     "TEMP R4;\n"
    1298     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1299     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1300     "ADD R0.xyz, R0, c[5];\n"
    1301     "RCP R0.z, R0.z;\n"
    1302     "MUL R0.xy, R0, R0.z;\n"
    1303     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1304     "MUL R0.xy, R0, c[6];\n"
    1305     "ADD R0.z, R0, R0.w;\n"
    1306     "ADD R0.x, R0, R0.y;\n"
    1307     "MUL R0.z, c[8].x, -R0;\n"
    1308     "MUL R0.y, R0.z, c[7];\n"
    1309     "MUL R0.x, R0, c[7];\n"
    1310     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1311     "MOV R0.z, c[7].x;\n"
    1312     "RSQ R0.y, R0.y;\n"
    1313     "RCP R0.y, R0.y;\n"
    1314     "MUL R0.z, c[8].x, R0;\n"
    1315     "ADD R0.x, -R0, R0.y;\n"
    1316     "RCP R0.z, R0.z;\n"
    1317     "MUL R0.x, R0, R0.z;\n"
    1318     "TEX R0, R0, texture[2], 1D;\n"
    1319     "MAX R1.x, R0.w, c[7].w;\n"
    1320     "RCP R1.x, R1.x;\n"
    1321     "MAD R1.xyz, -R0, R1.x, c[7].z;\n"
    1322     "MAX R2.xyz, R1, c[7].w;\n"
    1323     "MUL R1.xy, fragment.position, c[9];\n"
    1324     "TEX R1, R1, texture[0], 2D;\n"
    1325     "ADD R2.w, -R0, c[7].z;\n"
     1309    "ADD R2.w, -R0, c[9].z;\n"
    13261310    "MUL R3.xyz, R1, R2.w;\n"
    1327     "ADD R2.w, -R1, c[7].z;\n"
     1311    "ADD R2.w, -R1, c[9].z;\n"
    13281312    "MAD R4.xyz, R0, R2.w, R3;\n"
    1329     "MUL R3.xyz, R1, R0.w;\n"
     1313    "MUL R3.xyz, R0.w, R1;\n"
    13301314    "MUL R2.w, R0, R1;\n"
    13311315    "MAD R0.xyz, R0, R1.w, R3;\n"
     
    13401324    "ADD R0.z, R0.w, R1.w;\n"
    13411325    "MAD R2.w, -R0, R1, R0.z;\n"
    1342     "ADD R0.xy, fragment.position, c[0];\n"
    1343     "MUL R0.xy, R0, c[1];\n"
     1326    "ADD R0.xy, fragment.position, c[7];\n"
     1327    "MUL R0.xy, R0, c[5];\n"
    13441328    "TEX R0, R0, texture[1], 2D;\n"
    13451329    "ADD R2, R2, -R1;\n"
    1346     "DP4 R0.x, R0, c[2];\n"
     1330    "DP4 R0.x, R0, c[8];\n"
    13471331    "MAD result.color, R0.x, R2, R1;\n"
    13481332    "END\n"
     
    13511335static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN =
    13521336    "!!ARBfp1.0\n"
    1353     "PARAM c[10] = { program.local[0..6],\n"
    1354     "           { 2, 4, 1, 9.9999997e-06 },\n"
    1355     "           program.local[8..9] };\n"
     1337    "PARAM c[10] = { program.local[0..8],\n"
     1338    "           { 2, 4, 1, 9.9999997e-006 } };\n"
    13561339    "TEMP R0;\n"
    13571340    "TEMP R1;\n"
     
    13601343    "TEMP R4;\n"
    13611344    "TEMP R5;\n"
    1362     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1363     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1364     "ADD R0.xyz, R0, c[5];\n"
     1345    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1346    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1347    "ADD R0.xyz, R0, c[4];\n"
    13651348    "RCP R0.z, R0.z;\n"
    13661349    "MUL R0.xy, R0, R0.z;\n"
    13671350    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1368     "MUL R0.xy, R0, c[6];\n"
    13691351    "ADD R0.z, R0, R0.w;\n"
     1352    "MUL R0.xy, R0, c[0];\n"
    13701353    "ADD R0.x, R0, R0.y;\n"
    1371     "MUL R0.z, c[8].x, -R0;\n"
    1372     "MUL R0.y, R0.z, c[7];\n"
    1373     "MUL R0.x, R0, c[7];\n"
    1374     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1375     "MOV R0.z, c[7].x;\n"
    1376     "RSQ R0.y, R0.y;\n"
    1377     "RCP R0.y, R0.y;\n"
    1378     "MUL R0.z, c[8].x, R0;\n"
    1379     "MUL R1.xy, fragment.position, c[9];\n"
    1380     "TEX R1, R1, texture[0], 2D;\n"
    1381     "ADD R0.x, -R0, R0.y;\n"
    1382     "RCP R0.z, R0.z;\n"
    1383     "MUL R0.x, R0, R0.z;\n"
     1354    "MUL R0.z, -R0, c[1].x;\n"
     1355    "MUL R0.y, R0.x, c[9].x;\n"
     1356    "MUL R0.z, R0, c[9].y;\n"
     1357    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1358    "RSQ R0.z, R0.x;\n"
     1359    "MOV R0.x, c[9];\n"
     1360    "MUL R0.w, R0.x, c[1].x;\n"
     1361    "RCP R0.z, R0.z;\n"
     1362    "ADD R0.x, -R0.y, R0.z;\n"
     1363    "RCP R0.y, R0.w;\n"
     1364    "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     1365    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     1366    "MUL R0.x, R0, R0.y;\n"
    13841367    "TEX R0, R0, texture[2], 1D;\n"
    1385     "MUL R2.xyz, R1, R0.w;\n"
     1368    "MUL R2.xyz, R0.w, R1;\n"
    13861369    "MAD R3.xyz, R0, R1.w, R2;\n"
    13871370    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
    13881371    "MUL R4.xyz, R0.w, R2;\n"
    1389     "MAX R2.xyz, R0, c[7].w;\n"
    1390     "ADD R2.w, -R1, c[7].z;\n"
     1372    "MAX R2.xyz, R0, c[9].w;\n"
     1373    "ADD R2.w, -R1, c[9].z;\n"
    13911374    "MUL R5.xyz, R0, R2.w;\n"
    1392     "ADD R3.w, -R0, c[7].z;\n"
     1375    "ADD R3.w, -R0, c[9].z;\n"
    13931376    "RCP R2.x, R2.x;\n"
    13941377    "RCP R2.y, R2.y;\n"
     
    14041387    "ADD R0.z, R0.w, R1.w;\n"
    14051388    "MAD R2.w, -R0, R1, R0.z;\n"
    1406     "ADD R0.xy, fragment.position, c[0];\n"
    1407     "MUL R0.xy, R0, c[1];\n"
     1389    "ADD R0.xy, fragment.position, c[7];\n"
     1390    "MUL R0.xy, R0, c[5];\n"
    14081391    "TEX R0, R0, texture[1], 2D;\n"
    14091392    "ADD R2, R2, -R1;\n"
    1410     "DP4 R0.x, R0, c[2];\n"
     1393    "DP4 R0.x, R0, c[8];\n"
    14111394    "MAD result.color, R0.x, R2, R1;\n"
    14121395    "END\n"
     
    14151398static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT =
    14161399    "!!ARBfp1.0\n"
    1417     "PARAM c[10] = { program.local[0..6],\n"
    1418     "           { 2, 4, 1 },\n"
    1419     "           program.local[8..9] };\n"
     1400    "PARAM c[10] = { program.local[0..8],\n"
     1401    "           { 2, 4, 1 } };\n"
    14201402    "TEMP R0;\n"
    14211403    "TEMP R1;\n"
     
    14231405    "TEMP R3;\n"
    14241406    "TEMP R4;\n"
    1425     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1426     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1427     "ADD R0.xyz, R0, c[5];\n"
     1407    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1408    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1409    "ADD R0.xyz, R0, c[4];\n"
    14281410    "RCP R0.z, R0.z;\n"
    14291411    "MUL R0.xy, R0, R0.z;\n"
    14301412    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1431     "MUL R0.xy, R0, c[6];\n"
    14321413    "ADD R0.z, R0, R0.w;\n"
     1414    "MUL R0.xy, R0, c[0];\n"
    14331415    "ADD R0.x, R0, R0.y;\n"
    1434     "MUL R0.z, c[8].x, -R0;\n"
    1435     "MUL R0.y, R0.z, c[7];\n"
    1436     "MUL R0.x, R0, c[7];\n"
    1437     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1438     "MOV R0.z, c[7].x;\n"
    1439     "RSQ R0.y, R0.y;\n"
    1440     "RCP R0.y, R0.y;\n"
    1441     "MUL R0.z, c[8].x, R0;\n"
    1442     "MUL R1.xy, fragment.position, c[9];\n"
     1416    "MUL R0.y, R0.x, c[9].x;\n"
     1417    "MOV R0.x, c[9];\n"
     1418    "MUL R0.z, -R0, c[1].x;\n"
     1419    "MUL R0.z, R0, c[9].y;\n"
     1420    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1421    "MUL R1.xy, fragment.position, c[6];\n"
    14431422    "TEX R1, R1, texture[0], 2D;\n"
    1444     "ADD R0.x, -R0, R0.y;\n"
    1445     "RCP R0.z, R0.z;\n"
     1423    "MUL R0.w, R0.x, c[1].x;\n"
     1424    "RSQ R0.z, R0.z;\n"
     1425    "RCP R0.x, R0.z;\n"
     1426    "ADD R2.w, -R1, c[9].z;\n"
     1427    "RCP R0.z, R0.w;\n"
     1428    "ADD R0.x, -R0.y, R0;\n"
    14461429    "MUL R0.x, R0, R0.z;\n"
    14471430    "TEX R0, R0, texture[2], 1D;\n"
    1448     "ADD R2.w, -R1, c[7].z;\n"
    14491431    "ADD R3.xyz, R0.w, -R0;\n"
    14501432    "ADD R2.xyz, R1.w, -R1;\n"
    14511433    "MUL R2.xyz, R2, R3;\n"
    1452     "MUL R2.xyz, R2, c[7].x;\n"
     1434    "MUL R2.xyz, R2, c[9].x;\n"
    14531435    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    14541436    "MUL R4.xyz, R0, R2.w;\n"
    14551437    "MAD R2.xyz, R0, R2.w, R2;\n"
    14561438    "MUL R3.xyz, R0, R1;\n"
    1457     "ADD R2.w, -R0, c[7].z;\n"
    1458     "MAD R3.xyz, R3, c[7].x, R4;\n"
    1459     "MUL R0.xyz, R0, c[7].x;\n"
     1439    "ADD R2.w, -R0, c[9].z;\n"
     1440    "MAD R3.xyz, R3, c[9].x, R4;\n"
     1441    "MUL R0.xyz, R0, c[9].x;\n"
    14601442    "SGE R0.xyz, R0, R0.w;\n"
    14611443    "MAD R3.xyz, R1, R2.w, R3;\n"
     
    14651447    "ADD R0.z, R0.w, R1.w;\n"
    14661448    "MAD R2.w, -R0, R1, R0.z;\n"
    1467     "ADD R0.xy, fragment.position, c[0];\n"
    1468     "MUL R0.xy, R0, c[1];\n"
     1449    "ADD R0.xy, fragment.position, c[7];\n"
     1450    "MUL R0.xy, R0, c[5];\n"
    14691451    "TEX R0, R0, texture[1], 2D;\n"
    14701452    "ADD R2, R2, -R1;\n"
    1471     "DP4 R0.x, R0, c[2];\n"
     1453    "DP4 R0.x, R0, c[8];\n"
    14721454    "MAD result.color, R0.x, R2, R1;\n"
    14731455    "END\n"
     
    14761458static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT =
    14771459    "!!ARBfp1.0\n"
    1478     "PARAM c[11] = { program.local[0..6],\n"
    1479     "           { 2, 4, 1, 9.9999997e-06 },\n"
    1480     "           program.local[8..9],\n"
    1481     "           { 8, 3 } };\n"
     1460    "PARAM c[11] = { program.local[0..8],\n"
     1461    "           { 2, 4, 1, 9.9999997e-006 },\n"
     1462    "           { 16, 12, 3 } };\n"
    14821463    "TEMP R0;\n"
    14831464    "TEMP R1;\n"
     
    14871468    "TEMP R5;\n"
    14881469    "TEMP R6;\n"
    1489     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1490     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1491     "ADD R0.xyz, R0, c[5];\n"
     1470    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1471    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1472    "ADD R0.xyz, R0, c[4];\n"
    14921473    "RCP R0.z, R0.z;\n"
    14931474    "MUL R0.xy, R0, R0.z;\n"
    14941475    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1495     "MUL R0.xy, R0, c[6];\n"
    14961476    "ADD R0.z, R0, R0.w;\n"
     1477    "MUL R0.xy, R0, c[0];\n"
    14971478    "ADD R0.x, R0, R0.y;\n"
    1498     "MUL R0.z, c[8].x, -R0;\n"
    1499     "MUL R0.y, R0.z, c[7];\n"
    1500     "MUL R0.zw, fragment.position.xyxy, c[9].xyxy;\n"
     1479    "MUL R0.z, -R0, c[1].x;\n"
     1480    "MUL R0.y, R0.z, c[9];\n"
     1481    "MUL R0.x, R0, c[9];\n"
     1482    "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
    15011483    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1502     "MUL R0.x, R0, c[7];\n"
    15031484    "MAD R0.y, R0.x, R0.x, -R0;\n"
    1504     "MAX R0.z, R1.w, c[7].w;\n"
    1505     "RCP R2.w, R0.z;\n"
    1506     "MUL R2.xyz, R1, R2.w;\n"
    1507     "MUL R6.xyz, -R2, c[10].x;\n"
    1508     "MAD R3.xyz, -R1, R2.w, c[7].z;\n"
    15091485    "RSQ R0.y, R0.y;\n"
    15101486    "RCP R0.y, R0.y;\n"
    1511     "ADD R0.x, -R0, R0.y;\n"
    1512     "MOV R0.y, c[7].x;\n"
    1513     "MUL R0.y, c[8].x, R0;\n"
    1514     "RCP R0.y, R0.y;\n"
    1515     "MUL R0.x, R0, R0.y;\n"
     1487    "ADD R0.y, -R0.x, R0;\n"
     1488    "MOV R0.x, c[9];\n"
     1489    "MUL R0.x, R0, c[1];\n"
     1490    "MAX R0.z, R1.w, c[9].w;\n"
     1491    "RCP R0.z, R0.z;\n"
     1492    "MUL R3.xyz, R1, R0.z;\n"
     1493    "MAD R4.xyz, R3, c[10].x, -c[10].y;\n"
     1494    "RCP R0.x, R0.x;\n"
     1495    "MUL R0.x, R0.y, R0;\n"
    15161496    "TEX R0, R0, texture[2], 1D;\n"
    1517     "MAD R4.xyz, R0, c[7].x, -R0.w;\n"
    1518     "MUL R5.xyz, R3, R4;\n"
    1519     "MAD R3.xyz, -R3, R4, R0.w;\n"
    1520     "ADD R6.xyz, R6, c[10].y;\n"
    1521     "RSQ R2.x, R2.x;\n"
    1522     "RSQ R2.z, R2.z;\n"
    1523     "RSQ R2.y, R2.y;\n"
    1524     "MAD R5.xyz, -R5, R6, R0.w;\n"
    1525     "MUL R3.xyz, R1, R3;\n"
    1526     "ADD R2.w, -R1, c[7].z;\n"
    1527     "RCP R2.x, R2.x;\n"
    1528     "RCP R2.z, R2.z;\n"
    1529     "RCP R2.y, R2.y;\n"
    1530     "MAD R2.xyz, R2, R1.w, -R1;\n"
    1531     "MUL R6.xyz, R2, R4;\n"
    1532     "MUL R2.xyz, R1, R5;\n"
    1533     "MAD R6.xyz, R1, R0.w, R6;\n"
    1534     "MUL R4.xyz, R0, c[7].x;\n"
    1535     "MUL R5.xyz, R1, c[10].x;\n"
    1536     "ADD R6.xyz, R6, -R2;\n"
    1537     "SGE R5.xyz, R5, R1.w;\n"
    1538     "MUL R5.xyz, R5, R6;\n"
    1539     "ADD R2.xyz, R2, R5;\n"
    1540     "SGE R4.xyz, R4, R0.w;\n"
    1541     "ADD R2.xyz, R2, -R3;\n"
    1542     "MUL R2.xyz, R4, R2;\n"
    1543     "ADD R2.xyz, R3, R2;\n"
    1544     "MAD R0.xyz, R0, R2.w, R2;\n"
    1545     "ADD R2.x, -R0.w, c[7].z;\n"
    1546     "MAD R2.xyz, R1, R2.x, R0;\n"
     1497    "MAD R2.xyz, R0, c[9].x, -R0.w;\n"
     1498    "MAD R4.xyz, R3, R4, c[10].z;\n"
     1499    "MUL R5.xyz, R1.w, R2;\n"
     1500    "MUL R6.xyz, R5, R4;\n"
     1501    "RSQ R2.w, R3.x;\n"
     1502    "RCP R4.x, R2.w;\n"
     1503    "RSQ R2.w, R3.y;\n"
     1504    "RSQ R3.w, R3.z;\n"
     1505    "RCP R4.y, R2.w;\n"
     1506    "RCP R4.z, R3.w;\n"
     1507    "ADD R4.xyz, -R3, R4;\n"
     1508    "MUL R6.xyz, R3, R6;\n"
     1509    "MUL R4.xyz, R5, R4;\n"
     1510    "ADD R3.xyz, -R3, c[9].z;\n"
     1511    "MAD R2.xyz, R2, R3, R0.w;\n"
     1512    "MUL R3.xyz, R0, c[9].x;\n"
     1513    "MAD R5.xyz, R0.w, R1, R6;\n"
     1514    "MAD R4.xyz, R0.w, R1, R4;\n"
     1515    "ADD R6.xyz, R4, -R5;\n"
     1516    "MUL R4.xyz, R1, c[9].y;\n"
     1517    "SGE R4.xyz, R4, R1.w;\n"
     1518    "MAD R4.xyz, R4, R6, R5;\n"
     1519    "MAD R4.xyz, -R1, R2, R4;\n"
     1520    "SGE R3.xyz, R3, R0.w;\n"
     1521    "MUL R2.xyz, R1, R2;\n"
     1522    "ADD R2.w, -R1, c[9].z;\n"
     1523    "MAD R2.xyz, R3, R4, R2;\n"
     1524    "MAD R2.xyz, R0, R2.w, R2;\n"
     1525    "ADD R0.x, -R0.w, c[9].z;\n"
     1526    "MAD R2.xyz, R1, R0.x, R2;\n"
    15471527    "ADD R0.z, R0.w, R1.w;\n"
    15481528    "MAD R2.w, -R0, R1, R0.z;\n"
    1549     "ADD R0.xy, fragment.position, c[0];\n"
    1550     "MUL R0.xy, R0, c[1];\n"
     1529    "ADD R0.xy, fragment.position, c[7];\n"
     1530    "MUL R0.xy, R0, c[5];\n"
    15511531    "TEX R0, R0, texture[1], 2D;\n"
    15521532    "ADD R2, R2, -R1;\n"
    1553     "DP4 R0.x, R0, c[2];\n"
     1533    "DP4 R0.x, R0, c[8];\n"
    15541534    "MAD result.color, R0.x, R2, R1;\n"
    15551535    "END\n"
     
    15581538static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE =
    15591539    "!!ARBfp1.0\n"
    1560     "PARAM c[10] = { program.local[0..6],\n"
    1561     "           { 2, 4 },\n"
    1562     "           program.local[8..9] };\n"
    1563     "TEMP R0;\n"
    1564     "TEMP R1;\n"
    1565     "TEMP R2;\n"
    1566     "TEMP R3;\n"
    1567     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1568     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1569     "ADD R0.xyz, R0, c[5];\n"
     1540    "PARAM c[10] = { program.local[0..8],\n"
     1541    "           { 2, 4 } };\n"
     1542    "TEMP R0;\n"
     1543    "TEMP R1;\n"
     1544    "TEMP R2;\n"
     1545    "TEMP R3;\n"
     1546    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1547    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1548    "ADD R0.xyz, R0, c[4];\n"
    15701549    "RCP R0.z, R0.z;\n"
    15711550    "MUL R0.xy, R0, R0.z;\n"
    15721551    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    15731552    "ADD R0.z, R0, R0.w;\n"
    1574     "MUL R0.xy, R0, c[6];\n"
     1553    "MUL R0.xy, R0, c[0];\n"
    15751554    "ADD R0.x, R0, R0.y;\n"
    1576     "MUL R0.z, c[8].x, -R0;\n"
    1577     "MUL R0.y, R0.z, c[7];\n"
    1578     "MUL R0.x, R0, c[7];\n"
    1579     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1580     "RSQ R0.z, R0.y;\n"
    1581     "RCP R0.z, R0.z;\n"
    1582     "ADD R0.x, -R0, R0.z;\n"
    1583     "MUL R0.zw, fragment.position.xyxy, c[9].xyxy;\n"
    1584     "MOV R0.y, c[7].x;\n"
    1585     "MUL R0.y, c[8].x, R0;\n"
    1586     "RCP R0.y, R0.y;\n"
    1587     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1588     "MUL R0.x, R0, R0.y;\n"
    1589     "TEX R0, R0, texture[2], 1D;\n"
    1590     "ADD R3.xyz, R0, R1;\n"
    1591     "MUL R2.xyz, R1, R0.w;\n"
    1592     "MUL R0.xyz, R0, R1.w;\n"
    1593     "MIN R0.xyz, R0, R2;\n"
    1594     "MAD R2.xyz, -R0, c[7].x, R3;\n"
    1595     "ADD R0.z, R0.w, R1.w;\n"
    1596     "MAD R2.w, -R0, R1, R0.z;\n"
    1597     "ADD R0.xy, fragment.position, c[0];\n"
    1598     "MUL R0.xy, R0, c[1];\n"
    1599     "TEX R0, R0, texture[1], 2D;\n"
    1600     "ADD R2, R2, -R1;\n"
    1601     "DP4 R0.x, R0, c[2];\n"
    1602     "MAD result.color, R0.x, R2, R1;\n"
     1555    "MUL R0.z, -R0, c[1].x;\n"
     1556    "MUL R0.y, R0.x, c[9].x;\n"
     1557    "MUL R0.z, R0, c[9].y;\n"
     1558    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1559    "RSQ R0.z, R0.x;\n"
     1560    "MOV R0.x, c[9];\n"
     1561    "MUL R0.x, R0, c[1];\n"
     1562    "RCP R0.z, R0.z;\n"
     1563    "ADD R0.z, -R0.y, R0;\n"
     1564    "RCP R0.w, R0.x;\n"
     1565    "MUL R1.x, R0.z, R0.w;\n"
     1566    "MUL R0.xy, fragment.position, c[6];\n"
     1567    "TEX R0, R0, texture[0], 2D;\n"
     1568    "TEX R1, R1, texture[2], 1D;\n"
     1569    "ADD R2.xyz, R1, R0;\n"
     1570    "MUL R3.xyz, R1.w, R0;\n"
     1571    "MUL R1.xyz, R1, R0.w;\n"
     1572    "MIN R1.xyz, R1, R3;\n"
     1573    "MAD R2.xyz, -R1, c[9].x, R2;\n"
     1574    "ADD R1.z, R1.w, R0.w;\n"
     1575    "MAD R2.w, -R1, R0, R1.z;\n"
     1576    "ADD R1.xy, fragment.position, c[7];\n"
     1577    "MUL R1.xy, R1, c[5];\n"
     1578    "TEX R1, R1, texture[1], 2D;\n"
     1579    "ADD R2, R2, -R0;\n"
     1580    "DP4 R1.x, R1, c[8];\n"
     1581    "MAD result.color, R1.x, R2, R0;\n"
    16031582    "END\n"
    16041583    ;
     
    16061585static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION =
    16071586    "!!ARBfp1.0\n"
    1608     "PARAM c[10] = { program.local[0..6],\n"
    1609     "           { 2, 4, 1 },\n"
    1610     "           program.local[8..9] };\n"
    1611     "TEMP R0;\n"
    1612     "TEMP R1;\n"
    1613     "TEMP R2;\n"
    1614     "TEMP R3;\n"
    1615     "MUL R0.xyz, fragment.position.y, c[4];\n"
    1616     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    1617     "ADD R0.xyz, R0, c[5];\n"
    1618     "RCP R0.z, R0.z;\n"
    1619     "MUL R0.xy, R0, R0.z;\n"
    1620     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1621     "MUL R0.xy, R0, c[6];\n"
    1622     "ADD R0.z, R0, R0.w;\n"
    1623     "ADD R0.x, R0, R0.y;\n"
    1624     "MUL R0.z, c[8].x, -R0;\n"
    1625     "MUL R0.y, R0.z, c[7];\n"
    1626     "MUL R0.x, R0, c[7];\n"
    1627     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1628     "MOV R0.z, c[7].x;\n"
    1629     "RSQ R0.y, R0.y;\n"
    1630     "RCP R0.y, R0.y;\n"
    1631     "MUL R0.z, c[8].x, R0;\n"
    1632     "MUL R1.xy, fragment.position, c[9];\n"
    1633     "TEX R1, R1, texture[0], 2D;\n"
    1634     "ADD R0.x, -R0, R0.y;\n"
    1635     "RCP R0.z, R0.z;\n"
    1636     "MUL R0.x, R0, R0.z;\n"
    1637     "TEX R0, R0, texture[2], 1D;\n"
    1638     "MUL R2.xyz, R1, R0.w;\n"
    1639     "MAD R3.xyz, R0, R1.w, R2;\n"
    1640     "MUL R2.xyz, R0, R1;\n"
    1641     "MAD R2.xyz, -R2, c[7].x, R3;\n"
    1642     "ADD R2.w, -R1, c[7].z;\n"
    1643     "MAD R0.xyz, R0, R2.w, R2;\n"
    1644     "ADD R2.x, -R0.w, c[7].z;\n"
    1645     "MAD R2.xyz, R1, R2.x, R0;\n"
    1646     "ADD R0.z, R0.w, R1.w;\n"
    1647     "MAD R2.w, -R0, R1, R0.z;\n"
    1648     "ADD R0.xy, fragment.position, c[0];\n"
    1649     "MUL R0.xy, R0, c[1];\n"
    1650     "TEX R0, R0, texture[1], 2D;\n"
    1651     "ADD R2, R2, -R1;\n"
    1652     "DP4 R0.x, R0, c[2];\n"
    1653     "MAD result.color, R0.x, R2, R1;\n"
    1654     "END\n"
    1655     ;
    1656 
    1657 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    1658     "!!ARBfp1.0\n"
    1659     "PARAM c[9] = { program.local[0..3],\n"
    1660     "           { 2, 4, 1 },\n"
    1661     "           program.local[5..8] };\n"
    1662     "TEMP R0;\n"
    1663     "TEMP R1;\n"
    1664     "TEMP R2;\n"
    1665     "TEMP R3;\n"
    1666     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1667     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1668     "ADD R0.xyz, R0, c[2];\n"
     1587    "PARAM c[10] = { program.local[0..8],\n"
     1588    "           { 2, 4, 1 } };\n"
     1589    "TEMP R0;\n"
     1590    "TEMP R1;\n"
     1591    "TEMP R2;\n"
     1592    "TEMP R3;\n"
     1593    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1594    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1595    "ADD R0.xyz, R0, c[4];\n"
    16691596    "RCP R0.z, R0.z;\n"
    16701597    "MUL R0.xy, R0, R0.z;\n"
    16711598    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    16721599    "ADD R0.z, R0, R0.w;\n"
    1673     "MUL R0.xy, R0, c[3];\n"
     1600    "MUL R0.xy, R0, c[0];\n"
    16741601    "ADD R0.x, R0, R0.y;\n"
    1675     "MUL R0.z, c[5].x, -R0;\n"
    1676     "MUL R0.y, R0.z, c[4];\n"
    1677     "MUL R0.x, R0, c[4];\n"
    1678     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1679     "RSQ R0.z, R0.y;\n"
    1680     "RCP R0.z, R0.z;\n"
    1681     "ADD R0.x, -R0, R0.z;\n"
    1682     "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     1602    "MUL R0.z, -R0, c[1].x;\n"
     1603    "MUL R0.y, R0.x, c[9].x;\n"
     1604    "MUL R0.z, R0, c[9].y;\n"
     1605    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1606    "RSQ R0.z, R0.x;\n"
     1607    "MOV R0.x, c[9];\n"
     1608    "MUL R0.x, R0, c[1];\n"
     1609    "RCP R0.z, R0.z;\n"
     1610    "ADD R0.z, -R0.y, R0;\n"
     1611    "RCP R0.w, R0.x;\n"
     1612    "MUL R1.x, R0.z, R0.w;\n"
     1613    "MUL R0.xy, fragment.position, c[6];\n"
     1614    "TEX R0, R0, texture[0], 2D;\n"
     1615    "TEX R1, R1, texture[2], 1D;\n"
     1616    "MUL R2.xyz, R1.w, R0;\n"
     1617    "MAD R3.xyz, R1, R0.w, R2;\n"
     1618    "MUL R2.xyz, R1, R0;\n"
     1619    "MAD R2.xyz, -R2, c[9].x, R3;\n"
     1620    "ADD R2.w, -R0, c[9].z;\n"
     1621    "MAD R1.xyz, R1, R2.w, R2;\n"
     1622    "ADD R2.x, -R1.w, c[9].z;\n"
     1623    "MAD R2.xyz, R0, R2.x, R1;\n"
     1624    "ADD R1.z, R1.w, R0.w;\n"
     1625    "MAD R2.w, -R1, R0, R1.z;\n"
     1626    "ADD R1.xy, fragment.position, c[7];\n"
     1627    "MUL R1.xy, R1, c[5];\n"
     1628    "TEX R1, R1, texture[1], 2D;\n"
     1629    "ADD R2, R2, -R0;\n"
     1630    "DP4 R1.x, R1, c[8];\n"
     1631    "MAD result.color, R1.x, R2, R0;\n"
     1632    "END\n"
     1633    ;
     1634
     1635static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
     1636    "!!ARBfp1.0\n"
     1637    "PARAM c[9] = { program.local[0..7],\n"
     1638    "           { 2, 4, 1 } };\n"
     1639    "TEMP R0;\n"
     1640    "TEMP R1;\n"
     1641    "TEMP R2;\n"
     1642    "TEMP R3;\n"
     1643    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1644    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1645    "ADD R0.xyz, R0, c[4];\n"
     1646    "RCP R0.z, R0.z;\n"
     1647    "MUL R0.xy, R0, R0.z;\n"
     1648    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1649    "ADD R0.z, R0, R0.w;\n"
     1650    "MUL R0.xy, R0, c[0];\n"
     1651    "ADD R0.x, R0, R0.y;\n"
     1652    "MUL R0.z, -R0, c[1].x;\n"
     1653    "MUL R0.y, R0.x, c[8].x;\n"
     1654    "MUL R0.z, R0, c[8].y;\n"
     1655    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1656    "RSQ R0.x, R0.x;\n"
     1657    "RCP R0.z, R0.x;\n"
     1658    "ADD R0.y, -R0, R0.z;\n"
     1659    "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    16831660    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1684     "MUL R2.xyz, R1, c[8].y;\n"
    1685     "MOV R0.y, c[4].x;\n"
    1686     "MUL R0.y, c[5].x, R0;\n"
    1687     "RCP R0.y, R0.y;\n"
    1688     "MUL R0.x, R0, R0.y;\n"
     1661    "MUL R2.xyz, R1, c[5].y;\n"
     1662    "MOV R0.x, c[8];\n"
     1663    "MUL R0.x, R0, c[1];\n"
     1664    "RCP R0.x, R0.x;\n"
     1665    "MUL R0.x, R0.y, R0;\n"
    16891666    "TEX R0, R0, texture[1], 1D;\n"
    1690     "MUL R3.xyz, R2, R0.w;\n"
    1691     "MUL R2.xyz, R0, c[8].x;\n"
    1692     "MAD R2.xyz, R2, R1.w, R3;\n"
    1693     "ADD R2.w, -R1, c[4].z;\n"
    1694     "MUL R0.xyz, R0, c[7].y;\n"
    1695     "MAD R0.xyz, R0, R2.w, R2;\n"
    1696     "ADD R2.x, -R0.w, c[4].z;\n"
    1697     "MUL R1.xyz, R1, c[7].z;\n"
    1698     "MAD result.color.xyz, R1, R2.x, R0;\n"
     1667    "MUL R3.xyz, R0.w, R2;\n"
     1668    "MUL R2.xyz, R0, c[5].x;\n"
     1669    "MAD R2.xyz, R1.w, R2, R3;\n"
     1670    "ADD R2.w, -R1, c[8].z;\n"
     1671    "MUL R0.xyz, R0, c[6].y;\n"
     1672    "MAD R0.xyz, R2.w, R0, R2;\n"
     1673    "ADD R2.x, -R0.w, c[8].z;\n"
     1674    "MUL R1.xyz, R1, c[6].z;\n"
     1675    "MAD result.color.xyz, R2.x, R1, R0;\n"
    16991676    "MUL R0.x, R0.w, R1.w;\n"
    17001677    "MUL R0.z, R1.w, R2.x;\n"
    17011678    "MUL R0.y, R0.w, R2.w;\n"
    1702     "DP3 result.color.w, R0, c[7];\n"
     1679    "DP3 result.color.w, R0, c[6];\n"
    17031680    "END\n"
    17041681    ;
     
    17061683static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_MULTIPLY_NOMASK =
    17071684    "!!ARBfp1.0\n"
    1708     "PARAM c[7] = { program.local[0..3],\n"
    1709     "           { 2, 4, 1 },\n"
    1710     "           program.local[5..6] };\n"
    1711     "TEMP R0;\n"
    1712     "TEMP R1;\n"
    1713     "TEMP R2;\n"
    1714     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1715     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1716     "ADD R0.xyz, R0, c[2];\n"
     1685    "PARAM c[7] = { program.local[0..5],\n"
     1686    "           { 2, 4, 1 } };\n"
     1687    "TEMP R0;\n"
     1688    "TEMP R1;\n"
     1689    "TEMP R2;\n"
     1690    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1691    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1692    "ADD R0.xyz, R0, c[4];\n"
    17171693    "RCP R0.z, R0.z;\n"
    17181694    "MUL R0.xy, R0, R0.z;\n"
    17191695    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1720     "MUL R0.xy, R0, c[3];\n"
    17211696    "ADD R0.z, R0, R0.w;\n"
     1697    "MUL R0.xy, R0, c[0];\n"
    17221698    "ADD R0.x, R0, R0.y;\n"
    1723     "MUL R0.z, c[5].x, -R0;\n"
    1724     "MUL R0.y, R0.z, c[4];\n"
    1725     "MUL R0.x, R0, c[4];\n"
    1726     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1727     "RSQ R0.y, R0.y;\n"
    1728     "RCP R0.z, R0.y;\n"
    1729     "ADD R0.x, -R0, R0.z;\n"
    1730     "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     1699    "MUL R0.z, -R0, c[1].x;\n"
     1700    "MUL R0.y, R0.x, c[6].x;\n"
     1701    "MUL R0.z, R0, c[6].y;\n"
     1702    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1703    "RSQ R0.x, R0.x;\n"
     1704    "RCP R0.z, R0.x;\n"
     1705    "ADD R0.y, -R0, R0.z;\n"
     1706    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
    17311707    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    1732     "MOV R0.y, c[4].x;\n"
    1733     "MUL R0.y, c[5].x, R0;\n"
    1734     "RCP R0.y, R0.y;\n"
    1735     "MUL R0.x, R0, R0.y;\n"
     1708    "MOV R0.x, c[6];\n"
     1709    "MUL R0.x, R0, c[1];\n"
     1710    "RCP R0.x, R0.x;\n"
     1711    "MUL R0.x, R0.y, R0;\n"
    17361712    "TEX R0, R0, texture[1], 1D;\n"
    1737     "ADD R2.x, -R1.w, c[4].z;\n"
     1713    "ADD R2.x, -R1.w, c[6].z;\n"
    17381714    "MUL R2.xyz, R0, R2.x;\n"
    17391715    "MAD R0.xyz, R0, R1, R2;\n"
    17401716    "ADD R2.x, R0.w, R1.w;\n"
    1741     "ADD R2.y, -R0.w, c[4].z;\n"
     1717    "ADD R2.y, -R0.w, c[6].z;\n"
    17421718    "MAD result.color.xyz, R1, R2.y, R0;\n"
    17431719    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    17471723static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SCREEN_NOMASK =
    17481724    "!!ARBfp1.0\n"
    1749     "PARAM c[7] = { program.local[0..3],\n"
    1750     "           { 2, 4 },\n"
    1751     "           program.local[5..6] };\n"
    1752     "TEMP R0;\n"
    1753     "TEMP R1;\n"
    1754     "TEMP R2;\n"
    1755     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1756     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1757     "ADD R0.xyz, R0, c[2];\n"
     1725    "PARAM c[7] = { program.local[0..5],\n"
     1726    "           { 2, 4 } };\n"
     1727    "TEMP R0;\n"
     1728    "TEMP R1;\n"
     1729    "TEMP R2;\n"
     1730    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1731    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1732    "ADD R0.xyz, R0, c[4];\n"
    17581733    "RCP R0.z, R0.z;\n"
    17591734    "MUL R0.xy, R0, R0.z;\n"
    17601735    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    17611736    "ADD R0.z, R0, R0.w;\n"
    1762     "MUL R0.xy, R0, c[3];\n"
     1737    "MUL R0.xy, R0, c[0];\n"
    17631738    "ADD R0.x, R0, R0.y;\n"
    1764     "MUL R0.z, c[5].x, -R0;\n"
    1765     "MUL R0.y, R0.z, c[4];\n"
    1766     "MUL R0.x, R0, c[4];\n"
    1767     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1768     "RSQ R0.z, R0.y;\n"
    1769     "RCP R0.z, R0.z;\n"
    1770     "ADD R0.x, -R0, R0.z;\n"
    1771     "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
    1772     "MOV R0.y, c[4].x;\n"
    1773     "MUL R0.y, c[5].x, R0;\n"
    1774     "RCP R0.y, R0.y;\n"
     1739    "MUL R0.z, -R0, c[1].x;\n"
     1740    "MUL R0.y, R0.x, c[6].x;\n"
     1741    "MUL R0.z, R0, c[6].y;\n"
     1742    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1743    "RSQ R0.z, R0.x;\n"
     1744    "MOV R0.x, c[6];\n"
     1745    "MUL R0.w, R0.x, c[1].x;\n"
     1746    "RCP R0.z, R0.z;\n"
     1747    "ADD R0.x, -R0.y, R0.z;\n"
     1748    "RCP R0.y, R0.w;\n"
     1749    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
    17751750    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    17761751    "MUL R0.x, R0, R0.y;\n"
     
    17831758static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_OVERLAY_NOMASK =
    17841759    "!!ARBfp1.0\n"
    1785     "PARAM c[7] = { program.local[0..3],\n"
    1786     "           { 2, 4, 1 },\n"
    1787     "           program.local[5..6] };\n"
    1788     "TEMP R0;\n"
    1789     "TEMP R1;\n"
    1790     "TEMP R2;\n"
    1791     "TEMP R3;\n"
    1792     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1793     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1794     "ADD R0.xyz, R0, c[2];\n"
     1760    "PARAM c[7] = { program.local[0..5],\n"
     1761    "           { 2, 4, 1 } };\n"
     1762    "TEMP R0;\n"
     1763    "TEMP R1;\n"
     1764    "TEMP R2;\n"
     1765    "TEMP R3;\n"
     1766    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1767    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1768    "ADD R0.xyz, R0, c[4];\n"
    17951769    "RCP R0.z, R0.z;\n"
    17961770    "MUL R0.xy, R0, R0.z;\n"
    17971771    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1798     "MUL R0.xy, R0, c[3];\n"
    17991772    "ADD R0.z, R0, R0.w;\n"
     1773    "MUL R0.xy, R0, c[0];\n"
    18001774    "ADD R0.x, R0, R0.y;\n"
    1801     "MUL R0.z, c[5].x, -R0;\n"
    1802     "MUL R0.y, R0.z, c[4];\n"
    1803     "MUL R0.x, R0, c[4];\n"
    1804     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1805     "MOV R0.z, c[4].x;\n"
    1806     "RSQ R0.y, R0.y;\n"
    1807     "RCP R0.y, R0.y;\n"
    1808     "MUL R0.z, c[5].x, R0;\n"
    1809     "MUL R1.xy, fragment.position, c[6];\n"
     1775    "MUL R0.y, R0.x, c[6].x;\n"
     1776    "MOV R0.x, c[6];\n"
     1777    "MUL R0.z, -R0, c[1].x;\n"
     1778    "MUL R0.z, R0, c[6].y;\n"
     1779    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1780    "MUL R1.xy, fragment.position, c[5];\n"
    18101781    "TEX R1, R1, texture[0], 2D;\n"
    1811     "ADD R0.x, -R0, R0.y;\n"
    1812     "RCP R0.z, R0.z;\n"
     1782    "MUL R0.w, R0.x, c[1].x;\n"
     1783    "RSQ R0.z, R0.z;\n"
     1784    "RCP R0.x, R0.z;\n"
     1785    "ADD R2.w, -R1, c[6].z;\n"
     1786    "RCP R0.z, R0.w;\n"
     1787    "ADD R0.x, -R0.y, R0;\n"
    18131788    "MUL R0.x, R0, R0.z;\n"
    18141789    "TEX R0, R0, texture[1], 1D;\n"
     
    18161791    "ADD R2.xyz, R1.w, -R1;\n"
    18171792    "MUL R2.xyz, R2, R3;\n"
    1818     "ADD R2.w, -R1, c[4].z;\n"
    1819     "MUL R2.xyz, R2, c[4].x;\n"
     1793    "MUL R2.xyz, R2, c[6].x;\n"
    18201794    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    18211795    "MAD R2.xyz, R0, R2.w, R2;\n"
    18221796    "MUL R3.xyz, R0, R2.w;\n"
    18231797    "MUL R0.xyz, R0, R1;\n"
    1824     "ADD R2.w, -R0, c[4].z;\n"
    1825     "MAD R0.xyz, R0, c[4].x, R3;\n"
     1798    "ADD R2.w, -R0, c[6].z;\n"
     1799    "MAD R0.xyz, R0, c[6].x, R3;\n"
    18261800    "MAD R0.xyz, R1, R2.w, R0;\n"
    18271801    "MAD R2.xyz, R1, R2.w, R2;\n"
    1828     "MUL R1.xyz, R1, c[4].x;\n"
     1802    "MUL R1.xyz, R1, c[6].x;\n"
    18291803    "ADD R2.w, R0, R1;\n"
    18301804    "ADD R2.xyz, R2, -R0;\n"
     
    18371811static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DARKEN_NOMASK =
    18381812    "!!ARBfp1.0\n"
    1839     "PARAM c[7] = { program.local[0..3],\n"
    1840     "           { 2, 4, 1 },\n"
    1841     "           program.local[5..6] };\n"
    1842     "TEMP R0;\n"
    1843     "TEMP R1;\n"
    1844     "TEMP R2;\n"
    1845     "TEMP R3;\n"
    1846     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1847     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1848     "ADD R0.xyz, R0, c[2];\n"
     1813    "PARAM c[7] = { program.local[0..5],\n"
     1814    "           { 2, 4, 1 } };\n"
     1815    "TEMP R0;\n"
     1816    "TEMP R1;\n"
     1817    "TEMP R2;\n"
     1818    "TEMP R3;\n"
     1819    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1820    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1821    "ADD R0.xyz, R0, c[4];\n"
    18491822    "RCP R0.z, R0.z;\n"
    18501823    "MUL R0.xy, R0, R0.z;\n"
    18511824    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1852     "MUL R0.xy, R0, c[3];\n"
    18531825    "ADD R0.z, R0, R0.w;\n"
     1826    "MUL R0.xy, R0, c[0];\n"
    18541827    "ADD R0.x, R0, R0.y;\n"
    1855     "MUL R0.z, c[5].x, -R0;\n"
    1856     "MUL R0.y, R0.z, c[4];\n"
    1857     "MUL R0.x, R0, c[4];\n"
    1858     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1859     "MOV R0.z, c[4].x;\n"
    1860     "RSQ R0.y, R0.y;\n"
    1861     "RCP R0.y, R0.y;\n"
    1862     "MUL R0.z, c[5].x, R0;\n"
    1863     "MUL R1.xy, fragment.position, c[6];\n"
    1864     "TEX R1, R1, texture[0], 2D;\n"
    1865     "ADD R0.x, -R0, R0.y;\n"
    1866     "RCP R0.z, R0.z;\n"
     1828    "MUL R0.z, -R0, c[1].x;\n"
     1829    "MUL R0.y, R0.x, c[6].x;\n"
     1830    "MUL R0.z, R0, c[6].y;\n"
     1831    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1832    "RSQ R0.z, R0.x;\n"
     1833    "MOV R0.x, c[6];\n"
     1834    "MUL R0.w, R0.x, c[1].x;\n"
     1835    "RCP R0.z, R0.z;\n"
     1836    "ADD R0.x, -R0.y, R0.z;\n"
     1837    "RCP R0.y, R0.w;\n"
     1838    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     1839    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     1840    "MUL R0.x, R0, R0.y;\n"
     1841    "TEX R0, R0, texture[1], 1D;\n"
     1842    "MUL R2.xyz, R0, R1.w;\n"
     1843    "MUL R3.xyz, R0.w, R1;\n"
     1844    "MIN R2.xyz, R2, R3;\n"
     1845    "ADD R2.w, -R1, c[6].z;\n"
     1846    "MAD R0.xyz, R0, R2.w, R2;\n"
     1847    "ADD R2.x, R0.w, R1.w;\n"
     1848    "ADD R2.y, -R0.w, c[6].z;\n"
     1849    "MAD result.color.xyz, R1, R2.y, R0;\n"
     1850    "MAD result.color.w, -R0, R1, R2.x;\n"
     1851    "END\n"
     1852    ;
     1853
     1854static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN_NOMASK =
     1855    "!!ARBfp1.0\n"
     1856    "PARAM c[7] = { program.local[0..5],\n"
     1857    "           { 2, 4, 1 } };\n"
     1858    "TEMP R0;\n"
     1859    "TEMP R1;\n"
     1860    "TEMP R2;\n"
     1861    "TEMP R3;\n"
     1862    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1863    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1864    "ADD R0.xyz, R0, c[4];\n"
     1865    "RCP R0.z, R0.z;\n"
     1866    "MUL R0.xy, R0, R0.z;\n"
     1867    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1868    "ADD R0.z, R0, R0.w;\n"
     1869    "MUL R0.xy, R0, c[0];\n"
     1870    "ADD R0.x, R0, R0.y;\n"
     1871    "MUL R0.z, -R0, c[1].x;\n"
     1872    "MUL R0.y, R0.x, c[6].x;\n"
     1873    "MUL R0.z, R0, c[6].y;\n"
     1874    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1875    "RSQ R0.z, R0.x;\n"
     1876    "MOV R0.x, c[6];\n"
     1877    "MUL R0.w, R0.x, c[1].x;\n"
     1878    "RCP R0.z, R0.z;\n"
     1879    "ADD R0.x, -R0.y, R0.z;\n"
     1880    "RCP R0.y, R0.w;\n"
     1881    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     1882    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     1883    "MUL R0.x, R0, R0.y;\n"
     1884    "TEX R0, R0, texture[1], 1D;\n"
     1885    "MUL R2.xyz, R0, R1.w;\n"
     1886    "MUL R3.xyz, R0.w, R1;\n"
     1887    "MAX R2.xyz, R2, R3;\n"
     1888    "ADD R2.w, -R1, c[6].z;\n"
     1889    "MAD R0.xyz, R0, R2.w, R2;\n"
     1890    "ADD R2.x, R0.w, R1.w;\n"
     1891    "ADD R2.y, -R0.w, c[6].z;\n"
     1892    "MAD result.color.xyz, R1, R2.y, R0;\n"
     1893    "MAD result.color.w, -R0, R1, R2.x;\n"
     1894    "END\n"
     1895    ;
     1896
     1897static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE_NOMASK =
     1898    "!!ARBfp1.0\n"
     1899    "PARAM c[7] = { program.local[0..5],\n"
     1900    "           { 2, 4, 1, 1e-006 } };\n"
     1901    "TEMP R0;\n"
     1902    "TEMP R1;\n"
     1903    "TEMP R2;\n"
     1904    "TEMP R3;\n"
     1905    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1906    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1907    "ADD R0.xyz, R0, c[4];\n"
     1908    "RCP R0.z, R0.z;\n"
     1909    "MUL R0.xy, R0, R0.z;\n"
     1910    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     1911    "ADD R0.z, R0, R0.w;\n"
     1912    "MUL R0.xy, R0, c[0];\n"
     1913    "ADD R0.x, R0, R0.y;\n"
     1914    "MUL R0.y, R0.x, c[6].x;\n"
     1915    "MOV R0.x, c[6];\n"
     1916    "MUL R0.z, -R0, c[1].x;\n"
     1917    "MUL R0.z, R0, c[6].y;\n"
     1918    "MAD R0.z, R0.y, R0.y, -R0;\n"
     1919    "MUL R0.w, R0.x, c[1].x;\n"
     1920    "RSQ R0.z, R0.z;\n"
     1921    "RCP R0.x, R0.z;\n"
     1922    "RCP R0.z, R0.w;\n"
     1923    "ADD R0.x, -R0.y, R0;\n"
    18671924    "MUL R0.x, R0, R0.z;\n"
    18681925    "TEX R0, R0, texture[1], 1D;\n"
    1869     "MUL R2.xyz, R0, R1.w;\n"
    1870     "MUL R3.xyz, R1, R0.w;\n"
    1871     "MIN R2.xyz, R2, R3;\n"
    1872     "ADD R2.w, -R1, c[4].z;\n"
    1873     "MAD R0.xyz, R0, R2.w, R2;\n"
    1874     "ADD R2.x, R0.w, R1.w;\n"
    1875     "ADD R2.y, -R0.w, c[4].z;\n"
    1876     "MAD result.color.xyz, R1, R2.y, R0;\n"
    1877     "MAD result.color.w, -R0, R1, R2.x;\n"
    1878     "END\n"
    1879     ;
    1880 
    1881 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_LIGHTEN_NOMASK =
    1882     "!!ARBfp1.0\n"
    1883     "PARAM c[7] = { program.local[0..3],\n"
    1884     "           { 2, 4, 1 },\n"
    1885     "           program.local[5..6] };\n"
    1886     "TEMP R0;\n"
    1887     "TEMP R1;\n"
    1888     "TEMP R2;\n"
    1889     "TEMP R3;\n"
    1890     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1891     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1892     "ADD R0.xyz, R0, c[2];\n"
    1893     "RCP R0.z, R0.z;\n"
    1894     "MUL R0.xy, R0, R0.z;\n"
    1895     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1896     "MUL R0.xy, R0, c[3];\n"
    1897     "ADD R0.z, R0, R0.w;\n"
    1898     "ADD R0.x, R0, R0.y;\n"
    1899     "MUL R0.z, c[5].x, -R0;\n"
    1900     "MUL R0.y, R0.z, c[4];\n"
    1901     "MUL R0.x, R0, c[4];\n"
    1902     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1903     "MOV R0.z, c[4].x;\n"
    1904     "RSQ R0.y, R0.y;\n"
    1905     "RCP R0.y, R0.y;\n"
    1906     "MUL R0.z, c[5].x, R0;\n"
    1907     "MUL R1.xy, fragment.position, c[6];\n"
     1926    "MAX R1.x, R0.w, c[6].w;\n"
     1927    "RCP R1.x, R1.x;\n"
     1928    "MAD R1.xyz, -R0, R1.x, c[6].z;\n"
     1929    "MAX R2.xyz, R1, c[6].w;\n"
     1930    "MUL R1.xy, fragment.position, c[5];\n"
    19081931    "TEX R1, R1, texture[0], 2D;\n"
    1909     "ADD R0.x, -R0, R0.y;\n"
    1910     "RCP R0.z, R0.z;\n"
    1911     "MUL R0.x, R0, R0.z;\n"
    1912     "TEX R0, R0, texture[1], 1D;\n"
    1913     "MUL R2.xyz, R0, R1.w;\n"
    1914     "MUL R3.xyz, R1, R0.w;\n"
    1915     "MAX R2.xyz, R2, R3;\n"
    1916     "ADD R2.w, -R1, c[4].z;\n"
    1917     "MAD R0.xyz, R0, R2.w, R2;\n"
    1918     "ADD R2.x, R0.w, R1.w;\n"
    1919     "ADD R2.y, -R0.w, c[4].z;\n"
    1920     "MAD result.color.xyz, R1, R2.y, R0;\n"
    1921     "MAD result.color.w, -R0, R1, R2.x;\n"
    1922     "END\n"
    1923     ;
    1924 
    1925 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORDODGE_NOMASK =
    1926     "!!ARBfp1.0\n"
    1927     "PARAM c[7] = { program.local[0..3],\n"
    1928     "           { 2, 4, 1, 1e-06 },\n"
    1929     "           program.local[5..6] };\n"
    1930     "TEMP R0;\n"
    1931     "TEMP R1;\n"
    1932     "TEMP R2;\n"
    1933     "TEMP R3;\n"
    1934     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1935     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1936     "ADD R0.xyz, R0, c[2];\n"
    1937     "RCP R0.z, R0.z;\n"
    1938     "MUL R0.xy, R0, R0.z;\n"
    1939     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1940     "MUL R0.xy, R0, c[3];\n"
    1941     "ADD R0.z, R0, R0.w;\n"
    1942     "ADD R0.x, R0, R0.y;\n"
    1943     "MUL R0.z, c[5].x, -R0;\n"
    1944     "MUL R0.y, R0.z, c[4];\n"
    1945     "MUL R0.x, R0, c[4];\n"
    1946     "MAD R0.y, R0.x, R0.x, -R0;\n"
    1947     "MOV R0.z, c[4].x;\n"
    1948     "RSQ R0.y, R0.y;\n"
    1949     "RCP R0.y, R0.y;\n"
    1950     "MUL R0.z, c[5].x, R0;\n"
    1951     "ADD R0.x, -R0, R0.y;\n"
    1952     "RCP R0.z, R0.z;\n"
    1953     "MUL R0.x, R0, R0.z;\n"
    1954     "TEX R0, R0, texture[1], 1D;\n"
    1955     "MAX R1.x, R0.w, c[4].w;\n"
    1956     "RCP R1.x, R1.x;\n"
    1957     "MAD R1.xyz, -R0, R1.x, c[4].z;\n"
    1958     "MAX R2.xyz, R1, c[4].w;\n"
    1959     "MUL R1.xy, fragment.position, c[6];\n"
    1960     "TEX R1, R1, texture[0], 2D;\n"
    1961     "ADD R2.w, -R0, c[4].z;\n"
     1932    "ADD R2.w, -R0, c[6].z;\n"
    19621933    "MUL R3.xyz, R1, R2.w;\n"
    1963     "ADD R2.w, -R1, c[4].z;\n"
     1934    "ADD R2.w, -R1, c[6].z;\n"
    19641935    "MAD R3.xyz, R0, R2.w, R3;\n"
    1965     "MUL R1.xyz, R1, R0.w;\n"
     1936    "MUL R1.xyz, R0.w, R1;\n"
    19661937    "MAD R0.xyz, R0, R1.w, R1;\n"
    19671938    "MUL R2.w, R0, R1;\n"
     
    19811952static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_COLORBURN_NOMASK =
    19821953    "!!ARBfp1.0\n"
    1983     "PARAM c[7] = { program.local[0..3],\n"
    1984     "           { 2, 4, 1, 9.9999997e-06 },\n"
    1985     "           program.local[5..6] };\n"
     1954    "PARAM c[7] = { program.local[0..5],\n"
     1955    "           { 2, 4, 1, 9.9999997e-006 } };\n"
    19861956    "TEMP R0;\n"
    19871957    "TEMP R1;\n"
     
    19901960    "TEMP R4;\n"
    19911961    "TEMP R5;\n"
    1992     "MUL R0.xyz, fragment.position.y, c[1];\n"
    1993     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    1994     "ADD R0.xyz, R0, c[2];\n"
     1962    "MUL R0.xyz, fragment.position.y, c[3];\n"
     1963    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     1964    "ADD R0.xyz, R0, c[4];\n"
    19951965    "RCP R0.z, R0.z;\n"
    19961966    "MUL R0.xy, R0, R0.z;\n"
    19971967    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    1998     "MUL R0.xy, R0, c[3];\n"
    19991968    "ADD R0.z, R0, R0.w;\n"
     1969    "MUL R0.xy, R0, c[0];\n"
    20001970    "ADD R0.x, R0, R0.y;\n"
    2001     "MUL R0.z, c[5].x, -R0;\n"
    2002     "MUL R0.y, R0.z, c[4];\n"
    2003     "MUL R0.x, R0, c[4];\n"
    2004     "MAD R0.y, R0.x, R0.x, -R0;\n"
    2005     "MOV R0.z, c[4].x;\n"
    2006     "RSQ R0.y, R0.y;\n"
    2007     "RCP R0.y, R0.y;\n"
    2008     "MUL R0.z, c[5].x, R0;\n"
    2009     "MUL R1.xy, fragment.position, c[6];\n"
    2010     "TEX R1, R1, texture[0], 2D;\n"
    2011     "ADD R0.x, -R0, R0.y;\n"
    2012     "RCP R0.z, R0.z;\n"
    2013     "MUL R0.x, R0, R0.z;\n"
     1971    "MUL R0.z, -R0, c[1].x;\n"
     1972    "MUL R0.y, R0.x, c[6].x;\n"
     1973    "MUL R0.z, R0, c[6].y;\n"
     1974    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     1975    "RSQ R0.z, R0.x;\n"
     1976    "MOV R0.x, c[6];\n"
     1977    "MUL R0.w, R0.x, c[1].x;\n"
     1978    "RCP R0.z, R0.z;\n"
     1979    "ADD R0.x, -R0.y, R0.z;\n"
     1980    "RCP R0.y, R0.w;\n"
     1981    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     1982    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     1983    "MUL R0.x, R0, R0.y;\n"
    20141984    "TEX R0, R0, texture[1], 1D;\n"
    2015     "MUL R2.xyz, R1, R0.w;\n"
     1985    "MUL R2.xyz, R0.w, R1;\n"
    20161986    "MAD R3.xyz, R0, R1.w, R2;\n"
    2017     "ADD R2.w, -R1, c[4].z;\n"
     1987    "ADD R2.w, -R1, c[6].z;\n"
    20181988    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
    20191989    "MUL R4.xyz, R0.w, R2;\n"
    2020     "MAX R2.xyz, R0, c[4].w;\n"
     1990    "MAX R2.xyz, R0, c[6].w;\n"
    20211991    "MUL R5.xyz, R0, R2.w;\n"
    2022     "ADD R3.w, -R0, c[4].z;\n"
     1992    "ADD R3.w, -R0, c[6].z;\n"
    20231993    "RCP R2.x, R2.x;\n"
    20241994    "RCP R2.y, R2.y;\n"
     
    20392009static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_HARDLIGHT_NOMASK =
    20402010    "!!ARBfp1.0\n"
    2041     "PARAM c[7] = { program.local[0..3],\n"
    2042     "           { 2, 4, 1 },\n"
    2043     "           program.local[5..6] };\n"
     2011    "PARAM c[7] = { program.local[0..5],\n"
     2012    "           { 2, 4, 1 } };\n"
    20442013    "TEMP R0;\n"
    20452014    "TEMP R1;\n"
     
    20472016    "TEMP R3;\n"
    20482017    "TEMP R4;\n"
    2049     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2050     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2051     "ADD R0.xyz, R0, c[2];\n"
     2018    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2019    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2020    "ADD R0.xyz, R0, c[4];\n"
    20522021    "RCP R0.z, R0.z;\n"
    20532022    "MUL R0.xy, R0, R0.z;\n"
    20542023    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2055     "MUL R0.xy, R0, c[3];\n"
    20562024    "ADD R0.z, R0, R0.w;\n"
     2025    "MUL R0.xy, R0, c[0];\n"
    20572026    "ADD R0.x, R0, R0.y;\n"
    2058     "MUL R0.z, c[5].x, -R0;\n"
    2059     "MUL R0.y, R0.z, c[4];\n"
    2060     "MUL R0.x, R0, c[4];\n"
    2061     "MAD R0.y, R0.x, R0.x, -R0;\n"
    2062     "MOV R0.z, c[4].x;\n"
    2063     "RSQ R0.y, R0.y;\n"
    2064     "RCP R0.y, R0.y;\n"
    2065     "MUL R0.z, c[5].x, R0;\n"
    2066     "MUL R1.xy, fragment.position, c[6];\n"
     2027    "MUL R0.y, R0.x, c[6].x;\n"
     2028    "MOV R0.x, c[6];\n"
     2029    "MUL R0.z, -R0, c[1].x;\n"
     2030    "MUL R0.z, R0, c[6].y;\n"
     2031    "MAD R0.z, R0.y, R0.y, -R0;\n"
     2032    "MUL R1.xy, fragment.position, c[5];\n"
    20672033    "TEX R1, R1, texture[0], 2D;\n"
    2068     "ADD R0.x, -R0, R0.y;\n"
    2069     "RCP R0.z, R0.z;\n"
     2034    "MUL R0.w, R0.x, c[1].x;\n"
     2035    "RSQ R0.z, R0.z;\n"
     2036    "RCP R0.x, R0.z;\n"
     2037    "ADD R2.w, -R1, c[6].z;\n"
     2038    "RCP R0.z, R0.w;\n"
     2039    "ADD R0.x, -R0.y, R0;\n"
    20702040    "MUL R0.x, R0, R0.z;\n"
    20712041    "TEX R0, R0, texture[1], 1D;\n"
    2072     "ADD R2.w, -R1, c[4].z;\n"
    20732042    "ADD R3.xyz, R0.w, -R0;\n"
    20742043    "ADD R2.xyz, R1.w, -R1;\n"
    20752044    "MUL R2.xyz, R2, R3;\n"
    2076     "MUL R2.xyz, R2, c[4].x;\n"
     2045    "MUL R2.xyz, R2, c[6].x;\n"
    20772046    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    20782047    "MUL R4.xyz, R0, R2.w;\n"
    20792048    "MUL R3.xyz, R0, R1;\n"
    20802049    "MAD R2.xyz, R0, R2.w, R2;\n"
    2081     "ADD R2.w, -R0, c[4].z;\n"
    2082     "MUL R0.xyz, R0, c[4].x;\n"
     2050    "ADD R2.w, -R0, c[6].z;\n"
     2051    "MUL R0.xyz, R0, c[6].x;\n"
    20832052    "MAD R2.xyz, R1, R2.w, R2;\n"
    2084     "MAD R3.xyz, R3, c[4].x, R4;\n"
     2053    "MAD R3.xyz, R3, c[6].x, R4;\n"
    20852054    "MAD R1.xyz, R1, R2.w, R3;\n"
    20862055    "ADD R2.w, R0, R1;\n"
     
    20942063static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK =
    20952064    "!!ARBfp1.0\n"
    2096     "PARAM c[8] = { program.local[0..3],\n"
    2097     "           { 2, 4, 1, 9.9999997e-06 },\n"
    2098     "           program.local[5..6],\n"
    2099     "           { 8, 3 } };\n"
     2065    "PARAM c[8] = { program.local[0..5],\n"
     2066    "           { 2, 4, 1, 9.9999997e-006 },\n"
     2067    "           { 16, 12, 3 } };\n"
    21002068    "TEMP R0;\n"
    21012069    "TEMP R1;\n"
     
    21052073    "TEMP R5;\n"
    21062074    "TEMP R6;\n"
    2107     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2108     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2109     "ADD R0.xyz, R0, c[2];\n"
     2075    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2076    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2077    "ADD R0.xyz, R0, c[4];\n"
    21102078    "RCP R0.z, R0.z;\n"
    21112079    "MUL R0.xy, R0, R0.z;\n"
    21122080    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2113     "MUL R0.xy, R0, c[3];\n"
    21142081    "ADD R0.z, R0, R0.w;\n"
     2082    "MUL R0.xy, R0, c[0];\n"
    21152083    "ADD R0.x, R0, R0.y;\n"
    2116     "MUL R0.z, c[5].x, -R0;\n"
    2117     "MUL R0.y, R0.z, c[4];\n"
    2118     "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     2084    "MUL R0.z, -R0, c[1].x;\n"
     2085    "MUL R0.y, R0.z, c[6];\n"
     2086    "MUL R0.x, R0, c[6];\n"
     2087    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
    21192088    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    2120     "MUL R0.x, R0, c[4];\n"
    21212089    "MAD R0.y, R0.x, R0.x, -R0;\n"
    2122     "MAX R0.z, R1.w, c[4].w;\n"
    2123     "RCP R2.w, R0.z;\n"
    2124     "MUL R2.xyz, R1, R2.w;\n"
    2125     "MUL R6.xyz, -R2, c[7].x;\n"
    2126     "MAD R3.xyz, -R1, R2.w, c[4].z;\n"
    21272090    "RSQ R0.y, R0.y;\n"
    21282091    "RCP R0.y, R0.y;\n"
    2129     "ADD R0.x, -R0, R0.y;\n"
    2130     "MOV R0.y, c[4].x;\n"
    2131     "MUL R0.y, c[5].x, R0;\n"
    2132     "RCP R0.y, R0.y;\n"
     2092    "ADD R0.y, -R0.x, R0;\n"
     2093    "MOV R0.x, c[6];\n"
     2094    "MUL R0.x, R0, c[1];\n"
     2095    "MAX R0.z, R1.w, c[6].w;\n"
     2096    "RCP R0.z, R0.z;\n"
     2097    "MUL R3.xyz, R1, R0.z;\n"
     2098    "MAD R4.xyz, R3, c[7].x, -c[7].y;\n"
     2099    "RCP R0.x, R0.x;\n"
     2100    "MUL R0.x, R0.y, R0;\n"
     2101    "TEX R0, R0, texture[1], 1D;\n"
     2102    "MAD R2.xyz, R0, c[6].x, -R0.w;\n"
     2103    "MAD R4.xyz, R3, R4, c[7].z;\n"
     2104    "MUL R5.xyz, R1.w, R2;\n"
     2105    "MUL R6.xyz, R5, R4;\n"
     2106    "RSQ R2.w, R3.x;\n"
     2107    "RCP R4.x, R2.w;\n"
     2108    "RSQ R2.w, R3.y;\n"
     2109    "RSQ R3.w, R3.z;\n"
     2110    "RCP R4.y, R2.w;\n"
     2111    "RCP R4.z, R3.w;\n"
     2112    "ADD R4.xyz, -R3, R4;\n"
     2113    "MUL R6.xyz, R3, R6;\n"
     2114    "MUL R4.xyz, R5, R4;\n"
     2115    "ADD R3.xyz, -R3, c[6].z;\n"
     2116    "MAD R2.xyz, R2, R3, R0.w;\n"
     2117    "MUL R3.xyz, R0, c[6].x;\n"
     2118    "MAD R5.xyz, R0.w, R1, R6;\n"
     2119    "MAD R4.xyz, R0.w, R1, R4;\n"
     2120    "ADD R6.xyz, R4, -R5;\n"
     2121    "MUL R4.xyz, R1, c[6].y;\n"
     2122    "SGE R4.xyz, R4, R1.w;\n"
     2123    "MAD R4.xyz, R4, R6, R5;\n"
     2124    "MAD R4.xyz, -R1, R2, R4;\n"
     2125    "MUL R2.xyz, R1, R2;\n"
     2126    "SGE R3.xyz, R3, R0.w;\n"
     2127    "MAD R2.xyz, R3, R4, R2;\n"
     2128    "ADD R2.w, -R1, c[6].z;\n"
     2129    "MAD R2.xyz, R0, R2.w, R2;\n"
     2130    "ADD R0.x, R0.w, R1.w;\n"
     2131    "ADD R0.y, -R0.w, c[6].z;\n"
     2132    "MAD result.color.xyz, R1, R0.y, R2;\n"
     2133    "MAD result.color.w, -R0, R1, R0.x;\n"
     2134    "END\n"
     2135    ;
     2136
     2137static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE_NOMASK =
     2138    "!!ARBfp1.0\n"
     2139    "PARAM c[7] = { program.local[0..5],\n"
     2140    "           { 2, 4 } };\n"
     2141    "TEMP R0;\n"
     2142    "TEMP R1;\n"
     2143    "TEMP R2;\n"
     2144    "TEMP R3;\n"
     2145    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2146    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2147    "ADD R0.xyz, R0, c[4];\n"
     2148    "RCP R0.z, R0.z;\n"
     2149    "MUL R0.xy, R0, R0.z;\n"
     2150    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
     2151    "ADD R0.z, R0, R0.w;\n"
     2152    "MUL R0.xy, R0, c[0];\n"
     2153    "ADD R0.x, R0, R0.y;\n"
     2154    "MUL R0.z, -R0, c[1].x;\n"
     2155    "MUL R0.y, R0.x, c[6].x;\n"
     2156    "MUL R0.z, R0, c[6].y;\n"
     2157    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     2158    "RSQ R0.z, R0.x;\n"
     2159    "MOV R0.x, c[6];\n"
     2160    "MUL R0.w, R0.x, c[1].x;\n"
     2161    "RCP R0.z, R0.z;\n"
     2162    "ADD R0.x, -R0.y, R0.z;\n"
     2163    "RCP R0.y, R0.w;\n"
     2164    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     2165    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    21332166    "MUL R0.x, R0, R0.y;\n"
    21342167    "TEX R0, R0, texture[1], 1D;\n"
    2135     "MAD R4.xyz, R0, c[4].x, -R0.w;\n"
    2136     "MUL R5.xyz, R3, R4;\n"
    2137     "MAD R3.xyz, -R3, R4, R0.w;\n"
    2138     "ADD R6.xyz, R6, c[7].y;\n"
    2139     "RSQ R2.x, R2.x;\n"
    2140     "RSQ R2.z, R2.z;\n"
    2141     "RSQ R2.y, R2.y;\n"
    2142     "MAD R5.xyz, -R5, R6, R0.w;\n"
    2143     "MUL R3.xyz, R1, R3;\n"
    2144     "RCP R2.x, R2.x;\n"
    2145     "RCP R2.z, R2.z;\n"
    2146     "RCP R2.y, R2.y;\n"
    2147     "MAD R2.xyz, R2, R1.w, -R1;\n"
    2148     "MUL R6.xyz, R2, R4;\n"
    2149     "MUL R2.xyz, R1, R5;\n"
    2150     "MUL R4.xyz, R0, c[4].x;\n"
    2151     "MAD R6.xyz, R1, R0.w, R6;\n"
    2152     "MUL R5.xyz, R1, c[7].x;\n"
    2153     "ADD R6.xyz, R6, -R2;\n"
    2154     "SGE R5.xyz, R5, R1.w;\n"
    2155     "MUL R5.xyz, R5, R6;\n"
    2156     "ADD R2.xyz, R2, R5;\n"
    2157     "ADD R2.xyz, R2, -R3;\n"
    2158     "SGE R4.xyz, R4, R0.w;\n"
    2159     "MUL R2.xyz, R4, R2;\n"
    2160     "ADD R2.xyz, R3, R2;\n"
    2161     "ADD R2.w, -R1, c[4].z;\n"
    2162     "MAD R0.xyz, R0, R2.w, R2;\n"
    2163     "ADD R2.x, R0.w, R1.w;\n"
    2164     "ADD R2.y, -R0.w, c[4].z;\n"
    2165     "MAD result.color.xyz, R1, R2.y, R0;\n"
    2166     "MAD result.color.w, -R0, R1, R2.x;\n"
    2167     "END\n"
    2168     ;
    2169 
    2170 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_DIFFERENCE_NOMASK =
    2171     "!!ARBfp1.0\n"
    2172     "PARAM c[7] = { program.local[0..3],\n"
    2173     "           { 2, 4 },\n"
    2174     "           program.local[5..6] };\n"
    2175     "TEMP R0;\n"
    2176     "TEMP R1;\n"
    2177     "TEMP R2;\n"
    2178     "TEMP R3;\n"
    2179     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2180     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2181     "ADD R0.xyz, R0, c[2];\n"
    2182     "RCP R0.z, R0.z;\n"
    2183     "MUL R0.xy, R0, R0.z;\n"
    2184     "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2185     "MUL R0.xy, R0, c[3];\n"
    2186     "ADD R0.z, R0, R0.w;\n"
    2187     "ADD R0.x, R0, R0.y;\n"
    2188     "MUL R0.z, c[5].x, -R0;\n"
    2189     "MUL R0.y, R0.z, c[4];\n"
    2190     "MUL R0.x, R0, c[4];\n"
    2191     "MAD R0.y, R0.x, R0.x, -R0;\n"
    2192     "MOV R0.z, c[4].x;\n"
    2193     "RSQ R0.y, R0.y;\n"
    2194     "RCP R0.y, R0.y;\n"
    2195     "MUL R0.z, c[5].x, R0;\n"
    2196     "MUL R1.xy, fragment.position, c[6];\n"
    2197     "TEX R1, R1, texture[0], 2D;\n"
    2198     "ADD R0.x, -R0, R0.y;\n"
    2199     "RCP R0.z, R0.z;\n"
    2200     "MUL R0.x, R0, R0.z;\n"
    2201     "TEX R0, R0, texture[1], 1D;\n"
    22022168    "MUL R2.xyz, R0, R1.w;\n"
    2203     "MUL R3.xyz, R1, R0.w;\n"
     2169    "MUL R3.xyz, R0.w, R1;\n"
    22042170    "ADD R0.xyz, R0, R1;\n"
    22052171    "MIN R2.xyz, R2, R3;\n"
    22062172    "ADD R1.x, R0.w, R1.w;\n"
    2207     "MAD result.color.xyz, -R2, c[4].x, R0;\n"
     2173    "MAD result.color.xyz, -R2, c[6].x, R0;\n"
    22082174    "MAD result.color.w, -R0, R1, R1.x;\n"
    22092175    "END\n"
     
    22122178static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODES_EXCLUSION_NOMASK =
    22132179    "!!ARBfp1.0\n"
    2214     "PARAM c[7] = { program.local[0..3],\n"
    2215     "           { 2, 4, 1 },\n"
    2216     "           program.local[5..6] };\n"
    2217     "TEMP R0;\n"
    2218     "TEMP R1;\n"
    2219     "TEMP R2;\n"
    2220     "TEMP R3;\n"
    2221     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2222     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2223     "ADD R0.xyz, R0, c[2];\n"
     2180    "PARAM c[7] = { program.local[0..5],\n"
     2181    "           { 2, 4, 1 } };\n"
     2182    "TEMP R0;\n"
     2183    "TEMP R1;\n"
     2184    "TEMP R2;\n"
     2185    "TEMP R3;\n"
     2186    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2187    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2188    "ADD R0.xyz, R0, c[4];\n"
    22242189    "RCP R0.z, R0.z;\n"
    22252190    "MUL R0.xy, R0, R0.z;\n"
    22262191    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2227     "MUL R0.xy, R0, c[3];\n"
    22282192    "ADD R0.z, R0, R0.w;\n"
     2193    "MUL R0.xy, R0, c[0];\n"
    22292194    "ADD R0.x, R0, R0.y;\n"
    2230     "MUL R0.z, c[5].x, -R0;\n"
    2231     "MUL R0.y, R0.z, c[4];\n"
    2232     "MUL R0.x, R0, c[4];\n"
    2233     "MAD R0.y, R0.x, R0.x, -R0;\n"
    2234     "MOV R0.z, c[4].x;\n"
    2235     "RSQ R0.y, R0.y;\n"
    2236     "RCP R0.y, R0.y;\n"
    2237     "MUL R0.z, c[5].x, R0;\n"
    2238     "MUL R1.xy, fragment.position, c[6];\n"
    2239     "TEX R1, R1, texture[0], 2D;\n"
    2240     "ADD R0.x, -R0, R0.y;\n"
    2241     "RCP R0.z, R0.z;\n"
    2242     "MUL R0.x, R0, R0.z;\n"
     2195    "MUL R0.z, -R0, c[1].x;\n"
     2196    "MUL R0.y, R0.x, c[6].x;\n"
     2197    "MUL R0.z, R0, c[6].y;\n"
     2198    "MAD R0.x, R0.y, R0.y, -R0.z;\n"
     2199    "RSQ R0.z, R0.x;\n"
     2200    "MOV R0.x, c[6];\n"
     2201    "MUL R0.w, R0.x, c[1].x;\n"
     2202    "RCP R0.z, R0.z;\n"
     2203    "ADD R0.x, -R0.y, R0.z;\n"
     2204    "RCP R0.y, R0.w;\n"
     2205    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     2206    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     2207    "MUL R0.x, R0, R0.y;\n"
    22432208    "TEX R0, R0, texture[1], 1D;\n"
    2244     "MUL R2.xyz, R1, R0.w;\n"
     2209    "MUL R2.xyz, R0.w, R1;\n"
    22452210    "MAD R3.xyz, R0, R1.w, R2;\n"
    22462211    "MUL R2.xyz, R0, R1;\n"
    2247     "MAD R2.xyz, -R2, c[4].x, R3;\n"
    2248     "ADD R2.w, -R1, c[4].z;\n"
     2212    "MAD R2.xyz, -R2, c[6].x, R3;\n"
     2213    "ADD R2.w, -R1, c[6].z;\n"
    22492214    "MAD R0.xyz, R0, R2.w, R2;\n"
    22502215    "ADD R2.x, R0.w, R1.w;\n"
    2251     "ADD R2.y, -R0.w, c[4].z;\n"
     2216    "ADD R2.y, -R0.w, c[6].z;\n"
    22522217    "MAD result.color.xyz, R1, R2.y, R0;\n"
    22532218    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    22572222static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_MASK =
    22582223    "!!ARBfp1.0\n"
    2259     "PARAM c[9] = { program.local[0..3],\n"
    2260     "           { 2, 4 },\n"
    2261     "           program.local[5..8] };\n"
    2262     "TEMP R0;\n"
    2263     "TEMP R1;\n"
    2264     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2265     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2266     "ADD R0.xyz, R0, c[2];\n"
     2224    "PARAM c[9] = { program.local[0..7],\n"
     2225    "           { 2, 4 } };\n"
     2226    "TEMP R0;\n"
     2227    "TEMP R1;\n"
     2228    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2229    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2230    "ADD R0.xyz, R0, c[4];\n"
    22672231    "RCP R0.z, R0.z;\n"
    22682232    "MUL R0.xy, R0, R0.z;\n"
    22692233    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2270     "MUL R0.xy, R0, c[3];\n"
    22712234    "ADD R0.z, R0, R0.w;\n"
     2235    "MUL R0.xy, R0, c[0];\n"
    22722236    "ADD R0.x, R0, R0.y;\n"
    2273     "MUL R0.z, c[5].x, -R0;\n"
    2274     "MUL R0.y, R0.z, c[4];\n"
    2275     "MUL R0.x, R0, c[4];\n"
     2237    "MUL R0.z, -R0, c[1].x;\n"
     2238    "MUL R0.y, R0.z, c[8];\n"
     2239    "MUL R0.x, R0, c[8];\n"
    22762240    "MAD R0.y, R0.x, R0.x, -R0;\n"
    22772241    "RSQ R0.y, R0.y;\n"
    22782242    "RCP R0.y, R0.y;\n"
    22792243    "ADD R1.x, -R0, R0.y;\n"
    2280     "MOV R0.z, c[4].x;\n"
    2281     "MUL R0.z, c[5].x, R0;\n"
    2282     "RCP R1.y, R0.z;\n"
    2283     "ADD R0.xy, fragment.position, c[6];\n"
    2284     "MUL R0.xy, R0, c[7];\n"
    2285     "TEX R0, R0, texture[0], 2D;\n"
     2244    "MOV R0.x, c[8];\n"
     2245    "MUL R0.x, R0, c[1];\n"
     2246    "RCP R1.y, R0.x;\n"
     2247    "ADD R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     2248    "MUL R0.zw, R0, c[5].xyxy;\n"
     2249    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    22862250    "MUL R1.x, R1, R1.y;\n"
    2287     "DP4 R1.y, R0, c[8];\n"
     2251    "DP4 R1.y, R0, c[7];\n"
    22882252    "TEX R0, R1, texture[1], 1D;\n"
    22892253    "MUL result.color, R0, R1.y;\n"
     
    22932257static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_RADIAL_COMPOSITION_MODE_BLEND_MODE_NOMASK =
    22942258    "!!ARBfp1.0\n"
    2295     "PARAM c[6] = { program.local[0..3],\n"
    2296     "           { 2, 4 },\n"
    2297     "           program.local[5] };\n"
    2298     "TEMP R0;\n"
    2299     "MUL R0.xyz, fragment.position.y, c[1];\n"
    2300     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    2301     "ADD R0.xyz, R0, c[2];\n"
     2259    "PARAM c[6] = { program.local[0..4],\n"
     2260    "           { 2, 4 } };\n"
     2261    "TEMP R0;\n"
     2262    "MUL R0.xyz, fragment.position.y, c[3];\n"
     2263    "MAD R0.xyz, fragment.position.x, c[2], R0;\n"
     2264    "ADD R0.xyz, R0, c[4];\n"
    23022265    "RCP R0.z, R0.z;\n"
    23032266    "MUL R0.xy, R0, R0.z;\n"
    23042267    "MUL R0.zw, R0.xyxy, R0.xyxy;\n"
    2305     "MUL R0.xy, R0, c[3];\n"
     2268    "MUL R0.xy, R0, c[0];\n"
     2269    "ADD R0.z, R0, R0.w;\n"
    23062270    "ADD R0.x, R0, R0.y;\n"
    2307     "ADD R0.z, R0, R0.w;\n"
    2308     "MUL R0.z, c[5].x, -R0;\n"
    2309     "MUL R0.y, R0.z, c[4];\n"
    2310     "MUL R0.x, R0, c[4];\n"
    2311     "MAD R0.y, R0.x, R0.x, -R0;\n"
    2312     "MOV R0.z, c[4].x;\n"
    2313     "RSQ R0.y, R0.y;\n"
    2314     "MUL R0.z, c[5].x, R0;\n"
    2315     "RCP R0.y, R0.y;\n"
    2316     "RCP R0.z, R0.z;\n"
     2271    "MUL R0.z, -R0, c[1].x;\n"
     2272    "MUL R0.y, R0.z, c[5];\n"
     2273    "MUL R0.x, R0, c[5];\n"
     2274    "MAD R0.z, R0.x, R0.x, -R0.y;\n"
     2275    "MOV R0.y, c[5].x;\n"
     2276    "RSQ R0.z, R0.z;\n"
     2277    "MUL R0.w, R0.y, c[1].x;\n"
     2278    "RCP R0.y, R0.z;\n"
     2279    "RCP R0.z, R0.w;\n"
    23172280    "ADD R0.x, -R0, R0.y;\n"
    23182281    "MUL R0.x, R0, R0.z;\n"
     
    23232286static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    23242287    "!!ARBfp1.0\n"
    2325     "PARAM c[13] = { program.local[0..5],\n"
    2326     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2327     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2328     "           program.local[8],\n"
    2329     "           { 0.15915494 },\n"
    2330     "           program.local[10..12] };\n"
    2331     "TEMP R0;\n"
    2332     "TEMP R1;\n"
    2333     "TEMP R2;\n"
    2334     "TEMP R3;\n"
    2335     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2336     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2337     "ADD R0.xyz, R0, c[5];\n"
    2338     "RCP R0.z, R0.z;\n"
    2339     "MUL R0.xy, R0, R0.z;\n"
    2340     "ABS R0.w, R0.x;\n"
    2341     "ABS R0.z, R0.y;\n"
    2342     "ADD R0.z, R0, -R0.w;\n"
    2343     "ADD R0.w, R0.y, c[6].x;\n"
    2344     "ABS R0.z, R0;\n"
    2345     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2346     "ABS R0.z, -R0.y;\n"
    2347     "ADD R0.z, R0, c[6].y;\n"
    2348     "ADD R0.w, R0.x, R0.z;\n"
    2349     "ADD R1.x, R0.z, -R0;\n"
    2350     "RCP R1.y, R0.w;\n"
    2351     "RCP R1.x, R1.x;\n"
    2352     "MUL R0.w, R0, R1.x;\n"
    2353     "ADD R0.z, R0.x, -R0;\n"
    2354     "MUL R0.z, R0, R1.y;\n"
    2355     "CMP R0.z, R0.x, R0.w, R0;\n"
    2356     "MUL R0.w, R0.z, R0.z;\n"
    2357     "MOV R1.x, c[7].y;\n"
    2358     "CMP R0.x, R0, c[7], R1;\n"
    2359     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2360     "MAD R0.x, R0.w, R0.z, R0;\n"
    2361     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2362     "MAD R0.x, R0, R0.y, c[8];\n"
    2363     "MUL R0.x, R0, c[9];\n"
     2288    "PARAM c[13] = { program.local[0..9],\n"
     2289    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     2290    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     2291    "           { 0.33299461, 0.99999559, 1 } };\n"
     2292    "TEMP R0;\n"
     2293    "TEMP R1;\n"
     2294    "TEMP R2;\n"
     2295    "TEMP R3;\n"
     2296    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2297    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2298    "ADD R0.xyz, R0, c[3];\n"
     2299    "RCP R0.z, R0.z;\n"
     2300    "MUL R0.xy, R0, R0.z;\n"
     2301    "ABS R0.z, R0.x;\n"
     2302    "ABS R0.w, R0.y;\n"
     2303    "ADD R0.w, R0, -R0.z;\n"
     2304    "ADD R1.x, R0.y, c[10].y;\n"
     2305    "ABS R0.w, R0;\n"
     2306    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2307    "ABS R0.w, -R0.y;\n"
     2308    "MAX R1.x, R0.z, R0.w;\n"
     2309    "RCP R1.y, R1.x;\n"
     2310    "MIN R1.x, R0.z, R0.w;\n"
     2311    "MUL R1.x, R1, R1.y;\n"
     2312    "MUL R1.y, R1.x, R1.x;\n"
     2313    "MAD R1.z, R1.y, c[11].x, c[11].y;\n"
     2314    "MAD R1.z, R1, R1.y, -c[11];\n"
     2315    "MAD R1.z, R1, R1.y, c[11].w;\n"
     2316    "MAD R1.z, R1, R1.y, -c[12].x;\n"
     2317    "MAD R1.y, R1.z, R1, c[12];\n"
     2318    "MUL R1.x, R1.y, R1;\n"
     2319    "ADD R1.y, -R1.x, c[10].w;\n"
     2320    "ADD R0.z, -R0, R0.w;\n"
     2321    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2322    "ADD R0.w, -R0.z, c[10].z;\n"
     2323    "CMP R0.x, R0, R0.w, R0.z;\n"
     2324    "CMP R0.x, -R0.y, -R0, R0;\n"
     2325    "ADD R0.x, R0, c[0];\n"
     2326    "MUL R1.x, R0, c[10];\n"
     2327    "FLR R1.y, R1.x;\n"
     2328    "MUL R0.xy, fragment.position, c[7];\n"
     2329    "TEX R0, R0, texture[0], 2D;\n"
     2330    "ADD R1.x, R1, -R1.y;\n"
     2331    "TEX R1, R1, texture[2], 1D;\n"
     2332    "MUL R2.xyz, R0, c[4].y;\n"
     2333    "MUL R3.xyz, R1.w, R2;\n"
     2334    "MUL R2.xyz, R1, c[4].x;\n"
     2335    "MAD R2.xyz, R0.w, R2, R3;\n"
     2336    "ADD R3.xy, fragment.position, c[8];\n"
     2337    "ADD R2.w, -R0, c[12].z;\n"
     2338    "MUL R1.xyz, R1, c[5].y;\n"
     2339    "MAD R2.xyz, R2.w, R1, R2;\n"
     2340    "MUL R1.xyz, R0, c[5].z;\n"
     2341    "ADD R3.z, -R1.w, c[12];\n"
     2342    "MAD R2.xyz, R3.z, R1, R2;\n"
     2343    "MUL R1.y, R1.w, R2.w;\n"
     2344    "MUL R1.x, R1.w, R0.w;\n"
     2345    "MUL R1.z, R0.w, R3;\n"
     2346    "DP3 R2.w, R1, c[5];\n"
     2347    "MUL R3.xy, R3, c[6];\n"
     2348    "TEX R1, R3, texture[1], 2D;\n"
     2349    "ADD R2, R2, -R0;\n"
     2350    "DP4 R1.x, R1, c[9];\n"
     2351    "MAD result.color, R1.x, R2, R0;\n"
     2352    "END\n"
     2353    ;
     2354
     2355static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY =
     2356    "!!ARBfp1.0\n"
     2357    "PARAM c[11] = { program.local[0..7],\n"
     2358    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     2359    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     2360    "           { 0.33299461, 0.99999559, 1 } };\n"
     2361    "TEMP R0;\n"
     2362    "TEMP R1;\n"
     2363    "TEMP R2;\n"
     2364    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2365    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2366    "ADD R0.xyz, R0, c[3];\n"
     2367    "RCP R0.z, R0.z;\n"
     2368    "MUL R0.xy, R0, R0.z;\n"
     2369    "ABS R0.z, R0.x;\n"
     2370    "ABS R0.w, R0.y;\n"
     2371    "ADD R0.w, R0, -R0.z;\n"
     2372    "ADD R1.x, R0.y, c[8].y;\n"
     2373    "ABS R0.w, R0;\n"
     2374    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2375    "ABS R0.w, -R0.y;\n"
     2376    "MAX R1.x, R0.z, R0.w;\n"
     2377    "RCP R1.y, R1.x;\n"
     2378    "MIN R1.x, R0.z, R0.w;\n"
     2379    "MUL R1.x, R1, R1.y;\n"
     2380    "MUL R1.y, R1.x, R1.x;\n"
     2381    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     2382    "MAD R1.z, R1, R1.y, -c[9];\n"
     2383    "MAD R1.z, R1, R1.y, c[9].w;\n"
     2384    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     2385    "MAD R1.y, R1.z, R1, c[10];\n"
     2386    "MUL R1.x, R1.y, R1;\n"
     2387    "ADD R1.y, -R1.x, c[8].w;\n"
     2388    "ADD R0.z, -R0, R0.w;\n"
     2389    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2390    "ADD R0.w, -R0.z, c[8].z;\n"
     2391    "CMP R0.x, R0, R0.w, R0.z;\n"
     2392    "CMP R0.x, -R0.y, -R0, R0;\n"
     2393    "ADD R0.x, R0, c[0];\n"
     2394    "MUL R1.x, R0, c[8];\n"
     2395    "FLR R1.y, R1.x;\n"
     2396    "MUL R0.xy, fragment.position, c[5];\n"
     2397    "TEX R0, R0, texture[0], 2D;\n"
     2398    "ADD R1.x, R1, -R1.y;\n"
     2399    "TEX R1, R1, texture[2], 1D;\n"
     2400    "ADD R2.x, -R0.w, c[10].z;\n"
     2401    "MUL R2.xyz, R1, R2.x;\n"
     2402    "MAD R1.xyz, R1, R0, R2;\n"
     2403    "ADD R2.x, -R1.w, c[10].z;\n"
     2404    "MAD R2.xyz, R0, R2.x, R1;\n"
     2405    "ADD R1.z, R1.w, R0.w;\n"
     2406    "MAD R2.w, -R1, R0, R1.z;\n"
     2407    "ADD R1.xy, fragment.position, c[6];\n"
     2408    "MUL R1.xy, R1, c[4];\n"
     2409    "TEX R1, R1, texture[1], 2D;\n"
     2410    "ADD R2, R2, -R0;\n"
     2411    "DP4 R1.x, R1, c[7];\n"
     2412    "MAD result.color, R1.x, R2, R0;\n"
     2413    "END\n"
     2414    ;
     2415
     2416static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN =
     2417    "!!ARBfp1.0\n"
     2418    "PARAM c[11] = { program.local[0..7],\n"
     2419    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     2420    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     2421    "           { 0.33299461, 0.99999559 } };\n"
     2422    "TEMP R0;\n"
     2423    "TEMP R1;\n"
     2424    "TEMP R2;\n"
     2425    "TEMP R3;\n"
     2426    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2427    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2428    "ADD R0.xyz, R0, c[3];\n"
     2429    "RCP R0.z, R0.z;\n"
     2430    "MUL R0.xy, R0, R0.z;\n"
     2431    "ADD R3.xy, fragment.position, c[6];\n"
     2432    "ABS R0.z, R0.x;\n"
     2433    "ABS R0.w, R0.y;\n"
     2434    "ADD R0.w, R0, -R0.z;\n"
     2435    "ADD R1.x, R0.y, c[8].y;\n"
     2436    "ABS R0.w, R0;\n"
     2437    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2438    "ABS R0.w, -R0.y;\n"
     2439    "MAX R1.x, R0.z, R0.w;\n"
     2440    "RCP R1.y, R1.x;\n"
     2441    "MIN R1.x, R0.z, R0.w;\n"
     2442    "MUL R1.x, R1, R1.y;\n"
     2443    "MUL R1.y, R1.x, R1.x;\n"
     2444    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     2445    "MAD R1.z, R1, R1.y, -c[9];\n"
     2446    "MAD R1.z, R1, R1.y, c[9].w;\n"
     2447    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     2448    "MAD R1.y, R1.z, R1, c[10];\n"
     2449    "MUL R1.x, R1.y, R1;\n"
     2450    "ADD R0.z, -R0, R0.w;\n"
     2451    "ADD R1.y, -R1.x, c[8].w;\n"
     2452    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2453    "ADD R0.w, -R0.z, c[8].z;\n"
     2454    "CMP R0.x, R0, R0.w, R0.z;\n"
     2455    "CMP R0.x, -R0.y, -R0, R0;\n"
     2456    "ADD R0.x, R0, c[0];\n"
     2457    "MUL R0.x, R0, c[8];\n"
    23642458    "FLR R0.y, R0.x;\n"
    2365     "MUL R0.zw, fragment.position.xyxy, c[10].xyxy;\n"
    2366     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    2367     "ADD R0.x, R0, -R0.y;\n"
    2368     "TEX R0, R0, texture[2], 1D;\n"
    2369     "MUL R2.xyz, R1, c[12].y;\n"
    2370     "MUL R3.xyz, R2, R0.w;\n"
    2371     "MUL R2.xyz, R0, c[12].x;\n"
    2372     "MAD R2.xyz, R2, R1.w, R3;\n"
    2373     "ADD R3.xy, fragment.position, c[0];\n"
    2374     "ADD R2.w, -R1, c[7];\n"
    2375     "MUL R0.xyz, R0, c[11].y;\n"
    2376     "MAD R2.xyz, R0, R2.w, R2;\n"
    2377     "MUL R0.xyz, R1, c[11].z;\n"
    2378     "ADD R3.z, -R0.w, c[7].w;\n"
    2379     "MAD R2.xyz, R0, R3.z, R2;\n"
    2380     "MUL R0.y, R0.w, R2.w;\n"
    2381     "MUL R0.x, R0.w, R1.w;\n"
    2382     "MUL R0.z, R1.w, R3;\n"
    2383     "DP3 R2.w, R0, c[11];\n"
    2384     "MUL R3.xy, R3, c[1];\n"
    2385     "TEX R0, R3, texture[1], 2D;\n"
    2386     "ADD R2, R2, -R1;\n"
    2387     "DP4 R0.x, R0, c[2];\n"
    2388     "MAD result.color, R0.x, R2, R1;\n"
    2389     "END\n"
    2390     ;
    2391 
    2392 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY =
    2393     "!!ARBfp1.0\n"
    2394     "PARAM c[11] = { program.local[0..5],\n"
    2395     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2396     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2397     "           program.local[8],\n"
    2398     "           { 0.15915494 },\n"
    2399     "           program.local[10] };\n"
    2400     "TEMP R0;\n"
    2401     "TEMP R1;\n"
    2402     "TEMP R2;\n"
    2403     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2404     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2405     "ADD R0.xyz, R0, c[5];\n"
    2406     "RCP R0.z, R0.z;\n"
    2407     "MUL R0.xy, R0, R0.z;\n"
    2408     "ABS R0.w, R0.x;\n"
    2409     "ABS R0.z, R0.y;\n"
    2410     "ADD R0.z, R0, -R0.w;\n"
    2411     "ADD R0.w, R0.y, c[6].x;\n"
    2412     "ABS R0.z, R0;\n"
    2413     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2414     "ABS R0.z, -R0.y;\n"
    2415     "ADD R0.z, R0, c[6].y;\n"
    2416     "ADD R0.w, R0.x, R0.z;\n"
    2417     "ADD R1.x, R0.z, -R0;\n"
    2418     "RCP R1.y, R0.w;\n"
    2419     "RCP R1.x, R1.x;\n"
    2420     "MUL R0.w, R0, R1.x;\n"
    2421     "ADD R0.z, R0.x, -R0;\n"
    2422     "MUL R0.z, R0, R1.y;\n"
    2423     "CMP R0.z, R0.x, R0.w, R0;\n"
    2424     "MUL R0.w, R0.z, R0.z;\n"
    2425     "MOV R1.x, c[7].y;\n"
    2426     "CMP R0.x, R0, c[7], R1;\n"
    2427     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2428     "MAD R0.x, R0.w, R0.z, R0;\n"
    2429     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2430     "MAD R0.x, R0, R0.y, c[8];\n"
    2431     "MUL R0.x, R0, c[9];\n"
    2432     "FLR R0.y, R0.x;\n"
    2433     "MUL R0.zw, fragment.position.xyxy, c[10].xyxy;\n"
    2434     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    2435     "ADD R0.x, R0, -R0.y;\n"
    2436     "TEX R0, R0, texture[2], 1D;\n"
    2437     "ADD R2.x, -R1.w, c[7].w;\n"
    2438     "MUL R2.xyz, R0, R2.x;\n"
    2439     "MAD R0.xyz, R0, R1, R2;\n"
    2440     "ADD R2.x, -R0.w, c[7].w;\n"
    2441     "MAD R2.xyz, R1, R2.x, R0;\n"
    2442     "ADD R0.z, R0.w, R1.w;\n"
    2443     "MAD R2.w, -R0, R1, R0.z;\n"
    2444     "ADD R0.xy, fragment.position, c[0];\n"
    2445     "MUL R0.xy, R0, c[1];\n"
    2446     "TEX R0, R0, texture[1], 2D;\n"
    2447     "ADD R2, R2, -R1;\n"
    2448     "DP4 R0.x, R0, c[2];\n"
    2449     "MAD result.color, R0.x, R2, R1;\n"
    2450     "END\n"
    2451     ;
    2452 
    2453 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN =
    2454     "!!ARBfp1.0\n"
    2455     "PARAM c[11] = { program.local[0..5],\n"
    2456     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2457     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2458     "           program.local[8],\n"
    2459     "           { 0.15915494 },\n"
    2460     "           program.local[10] };\n"
    2461     "TEMP R0;\n"
    2462     "TEMP R1;\n"
    2463     "TEMP R2;\n"
    2464     "TEMP R3;\n"
    2465     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2466     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2467     "ADD R0.xyz, R0, c[5];\n"
    2468     "RCP R0.z, R0.z;\n"
    2469     "MUL R0.xy, R0, R0.z;\n"
    2470     "ADD R3.xy, fragment.position, c[0];\n"
    2471     "ABS R0.w, R0.x;\n"
    2472     "ABS R0.z, R0.y;\n"
    2473     "ADD R0.z, R0, -R0.w;\n"
    2474     "ADD R0.w, R0.y, c[6].x;\n"
    2475     "ABS R0.z, R0;\n"
    2476     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2477     "ABS R0.z, -R0.y;\n"
    2478     "ADD R0.z, R0, c[6].y;\n"
    2479     "ADD R0.w, R0.x, R0.z;\n"
    2480     "ADD R1.x, R0.z, -R0;\n"
    2481     "RCP R1.y, R0.w;\n"
    2482     "RCP R1.x, R1.x;\n"
    2483     "MUL R0.w, R0, R1.x;\n"
    2484     "ADD R0.z, R0.x, -R0;\n"
    2485     "MUL R0.z, R0, R1.y;\n"
    2486     "CMP R0.z, R0.x, R0.w, R0;\n"
    2487     "MUL R0.w, R0.z, R0.z;\n"
    2488     "MOV R1.x, c[7].y;\n"
    2489     "CMP R0.x, R0, c[7], R1;\n"
    2490     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2491     "MUL R1.xy, fragment.position, c[10];\n"
    2492     "TEX R1, R1, texture[0], 2D;\n"
    2493     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2494     "MAD R0.x, R0.w, R0.z, R0;\n"
    2495     "MAD R0.x, R0, R0.y, c[8];\n"
    2496     "MUL R0.x, R0, c[9];\n"
     2459    "ADD R0.z, R0.x, -R0.y;\n"
     2460    "TEX R1, R0.z, texture[2], 1D;\n"
     2461    "MUL R0.xy, fragment.position, c[5];\n"
     2462    "TEX R0, R0, texture[0], 2D;\n"
     2463    "ADD R2, R1, R0;\n"
     2464    "MAD R2, -R1, R0, R2;\n"
     2465    "MUL R3.xy, R3, c[4];\n"
     2466    "TEX R1, R3, texture[1], 2D;\n"
     2467    "ADD R2, R2, -R0;\n"
     2468    "DP4 R1.x, R1, c[7];\n"
     2469    "MAD result.color, R1.x, R2, R0;\n"
     2470    "END\n"
     2471    ;
     2472
     2473static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY =
     2474    "!!ARBfp1.0\n"
     2475    "PARAM c[11] = { program.local[0..7],\n"
     2476    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     2477    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     2478    "           { 3.141593, 0.15915494, 2, 1 } };\n"
     2479    "TEMP R0;\n"
     2480    "TEMP R1;\n"
     2481    "TEMP R2;\n"
     2482    "TEMP R3;\n"
     2483    "TEMP R4;\n"
     2484    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2485    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2486    "ADD R0.xyz, R0, c[3];\n"
     2487    "RCP R0.z, R0.z;\n"
     2488    "MUL R0.xy, R0, R0.z;\n"
     2489    "ABS R0.z, R0.x;\n"
     2490    "ABS R0.w, R0.y;\n"
     2491    "ADD R0.w, R0, -R0.z;\n"
     2492    "ADD R1.x, R0.y, c[8];\n"
     2493    "ABS R0.w, R0;\n"
     2494    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2495    "ABS R0.w, -R0.y;\n"
     2496    "MAX R1.x, R0.z, R0.w;\n"
     2497    "RCP R1.y, R1.x;\n"
     2498    "MIN R1.x, R0.z, R0.w;\n"
     2499    "MUL R1.x, R1, R1.y;\n"
     2500    "MUL R1.y, R1.x, R1.x;\n"
     2501    "MAD R1.z, R1.y, c[8].y, c[8];\n"
     2502    "MAD R1.z, R1, R1.y, -c[8].w;\n"
     2503    "MAD R1.z, R1, R1.y, c[9].x;\n"
     2504    "MAD R1.z, R1, R1.y, -c[9].y;\n"
     2505    "MAD R1.y, R1.z, R1, c[9].z;\n"
     2506    "MUL R1.x, R1.y, R1;\n"
     2507    "ADD R0.z, -R0, R0.w;\n"
     2508    "ADD R1.y, -R1.x, c[9].w;\n"
     2509    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2510    "ADD R0.w, -R0.z, c[10].x;\n"
     2511    "CMP R0.x, R0, R0.w, R0.z;\n"
     2512    "CMP R0.x, -R0.y, -R0, R0;\n"
     2513    "ADD R0.x, R0, c[0];\n"
     2514    "MUL R0.x, R0, c[10].y;\n"
    24972515    "FLR R0.y, R0.x;\n"
    24982516    "ADD R0.x, R0, -R0.y;\n"
    24992517    "TEX R0, R0, texture[2], 1D;\n"
    2500     "ADD R2, R0, R1;\n"
    2501     "MAD R2, -R0, R1, R2;\n"
    2502     "MUL R3.xy, R3, c[1];\n"
    2503     "TEX R0, R3, texture[1], 2D;\n"
    2504     "ADD R2, R2, -R1;\n"
    2505     "DP4 R0.x, R0, c[2];\n"
    2506     "MAD result.color, R0.x, R2, R1;\n"
    2507     "END\n"
    2508     ;
    2509 
    2510 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY =
    2511     "!!ARBfp1.0\n"
    2512     "PARAM c[11] = { program.local[0..5],\n"
    2513     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2514     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2515     "           program.local[8],\n"
    2516     "           { 0.15915494, 2 },\n"
    2517     "           program.local[10] };\n"
    2518     "TEMP R0;\n"
    2519     "TEMP R1;\n"
    2520     "TEMP R2;\n"
    2521     "TEMP R3;\n"
    2522     "TEMP R4;\n"
    2523     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2524     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2525     "ADD R0.xyz, R0, c[5];\n"
    2526     "RCP R0.z, R0.z;\n"
    2527     "MUL R0.xy, R0, R0.z;\n"
    2528     "ABS R0.w, R0.x;\n"
    2529     "ABS R0.z, R0.y;\n"
    2530     "ADD R0.z, R0, -R0.w;\n"
    2531     "ADD R0.w, R0.y, c[6].x;\n"
    2532     "ABS R0.z, R0;\n"
    2533     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2534     "ABS R0.z, -R0.y;\n"
    2535     "ADD R0.z, R0, c[6].y;\n"
    2536     "ADD R0.w, R0.x, R0.z;\n"
    2537     "ADD R1.x, R0.z, -R0;\n"
    2538     "RCP R1.y, R0.w;\n"
    2539     "RCP R1.x, R1.x;\n"
    2540     "MUL R0.w, R0, R1.x;\n"
    2541     "ADD R0.z, R0.x, -R0;\n"
    2542     "MUL R0.z, R0, R1.y;\n"
    2543     "CMP R0.z, R0.x, R0.w, R0;\n"
    2544     "MUL R0.w, R0.z, R0.z;\n"
    2545     "MOV R1.x, c[7].y;\n"
    2546     "CMP R0.x, R0, c[7], R1;\n"
    2547     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2548     "MUL R1.xy, fragment.position, c[10];\n"
     2518    "MUL R1.xy, fragment.position, c[5];\n"
    25492519    "TEX R1, R1, texture[0], 2D;\n"
    2550     "ADD R2.w, -R1, c[7];\n"
    2551     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2552     "MAD R0.x, R0.w, R0.z, R0;\n"
    2553     "MAD R0.x, R0, R0.y, c[8];\n"
    2554     "MUL R0.x, R0, c[9];\n"
    2555     "FLR R0.y, R0.x;\n"
    2556     "ADD R0.x, R0, -R0.y;\n"
    2557     "TEX R0, R0, texture[2], 1D;\n"
     2520    "ADD R2.w, -R1, c[10];\n"
    25582521    "ADD R3.xyz, R0.w, -R0;\n"
    25592522    "ADD R2.xyz, R1.w, -R1;\n"
    25602523    "MUL R2.xyz, R2, R3;\n"
    2561     "MUL R2.xyz, R2, c[9].y;\n"
     2524    "MUL R2.xyz, R2, c[10].z;\n"
    25622525    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    25632526    "MUL R4.xyz, R0, R2.w;\n"
    25642527    "MUL R3.xyz, R0, R1;\n"
    25652528    "MAD R0.xyz, R0, R2.w, R2;\n"
    2566     "ADD R2.x, -R0.w, c[7].w;\n"
    2567     "MAD R3.xyz, R3, c[9].y, R4;\n"
     2529    "ADD R2.x, -R0.w, c[10].w;\n"
     2530    "MAD R3.xyz, R3, c[10].z, R4;\n"
    25682531    "MAD R3.xyz, R1, R2.x, R3;\n"
    25692532    "MAD R0.xyz, R1, R2.x, R0;\n"
    2570     "MUL R2.xyz, R1, c[9].y;\n"
     2533    "MUL R2.xyz, R1, c[10].z;\n"
    25712534    "ADD R0.xyz, R0, -R3;\n"
    25722535    "SGE R2.xyz, R2, R1.w;\n"
     
    25742537    "ADD R0.z, R0.w, R1.w;\n"
    25752538    "MAD R2.w, -R0, R1, R0.z;\n"
    2576     "ADD R0.xy, fragment.position, c[0];\n"
    2577     "MUL R0.xy, R0, c[1];\n"
     2539    "ADD R0.xy, fragment.position, c[6];\n"
     2540    "MUL R0.xy, R0, c[4];\n"
    25782541    "TEX R0, R0, texture[1], 2D;\n"
    25792542    "ADD R2, R2, -R1;\n"
    2580     "DP4 R0.x, R0, c[2];\n"
     2543    "DP4 R0.x, R0, c[7];\n"
    25812544    "MAD result.color, R0.x, R2, R1;\n"
    25822545    "END\n"
     
    25852548static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN =
    25862549    "!!ARBfp1.0\n"
    2587     "PARAM c[11] = { program.local[0..5],\n"
    2588     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2589     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2590     "           program.local[8],\n"
    2591     "           { 0.15915494 },\n"
    2592     "           program.local[10] };\n"
    2593     "TEMP R0;\n"
    2594     "TEMP R1;\n"
    2595     "TEMP R2;\n"
    2596     "TEMP R3;\n"
    2597     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2598     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2599     "ADD R0.xyz, R0, c[5];\n"
    2600     "RCP R0.z, R0.z;\n"
    2601     "MUL R0.xy, R0, R0.z;\n"
    2602     "ABS R0.w, R0.x;\n"
    2603     "ABS R0.z, R0.y;\n"
    2604     "ADD R0.z, R0, -R0.w;\n"
    2605     "ADD R0.w, R0.y, c[6].x;\n"
    2606     "ABS R0.z, R0;\n"
    2607     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2608     "ABS R0.z, -R0.y;\n"
    2609     "ADD R0.z, R0, c[6].y;\n"
    2610     "ADD R0.w, R0.x, R0.z;\n"
    2611     "ADD R1.x, R0.z, -R0;\n"
    2612     "RCP R1.y, R0.w;\n"
    2613     "RCP R1.x, R1.x;\n"
    2614     "MUL R0.w, R0, R1.x;\n"
    2615     "ADD R0.z, R0.x, -R0;\n"
    2616     "MUL R0.z, R0, R1.y;\n"
    2617     "CMP R0.z, R0.x, R0.w, R0;\n"
    2618     "MUL R0.w, R0.z, R0.z;\n"
    2619     "MOV R1.x, c[7].y;\n"
    2620     "CMP R0.x, R0, c[7], R1;\n"
    2621     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2622     "MUL R1.xy, fragment.position, c[10];\n"
    2623     "TEX R1, R1, texture[0], 2D;\n"
    2624     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2625     "MAD R0.x, R0.w, R0.z, R0;\n"
    2626     "MAD R0.x, R0, R0.y, c[8];\n"
    2627     "MUL R0.x, R0, c[9];\n"
     2550    "PARAM c[11] = { program.local[0..7],\n"
     2551    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     2552    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     2553    "           { 0.33299461, 0.99999559, 1 } };\n"
     2554    "TEMP R0;\n"
     2555    "TEMP R1;\n"
     2556    "TEMP R2;\n"
     2557    "TEMP R3;\n"
     2558    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2559    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2560    "ADD R0.xyz, R0, c[3];\n"
     2561    "RCP R0.z, R0.z;\n"
     2562    "MUL R0.xy, R0, R0.z;\n"
     2563    "ABS R0.z, R0.x;\n"
     2564    "ABS R0.w, R0.y;\n"
     2565    "ADD R0.w, R0, -R0.z;\n"
     2566    "ADD R1.x, R0.y, c[8].y;\n"
     2567    "ABS R0.w, R0;\n"
     2568    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2569    "ABS R0.w, -R0.y;\n"
     2570    "MAX R1.x, R0.z, R0.w;\n"
     2571    "RCP R1.y, R1.x;\n"
     2572    "MIN R1.x, R0.z, R0.w;\n"
     2573    "MUL R1.x, R1, R1.y;\n"
     2574    "MUL R1.y, R1.x, R1.x;\n"
     2575    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     2576    "MAD R1.z, R1, R1.y, -c[9];\n"
     2577    "MAD R1.z, R1, R1.y, c[9].w;\n"
     2578    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     2579    "MAD R1.y, R1.z, R1, c[10];\n"
     2580    "MUL R1.x, R1.y, R1;\n"
     2581    "ADD R1.y, -R1.x, c[8].w;\n"
     2582    "ADD R0.z, -R0, R0.w;\n"
     2583    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2584    "ADD R0.w, -R0.z, c[8].z;\n"
     2585    "CMP R0.x, R0, R0.w, R0.z;\n"
     2586    "CMP R0.x, -R0.y, -R0, R0;\n"
     2587    "ADD R0.x, R0, c[0];\n"
     2588    "MUL R0.z, R0.x, c[8].x;\n"
     2589    "FLR R0.w, R0.z;\n"
     2590    "ADD R1.x, R0.z, -R0.w;\n"
     2591    "MUL R0.xy, fragment.position, c[5];\n"
     2592    "TEX R0, R0, texture[0], 2D;\n"
     2593    "TEX R1, R1, texture[2], 1D;\n"
     2594    "MUL R3.xyz, R1.w, R0;\n"
     2595    "MUL R2.xyz, R1, R0.w;\n"
     2596    "MIN R2.xyz, R2, R3;\n"
     2597    "ADD R2.w, -R0, c[10].z;\n"
     2598    "MAD R1.xyz, R1, R2.w, R2;\n"
     2599    "ADD R2.x, -R1.w, c[10].z;\n"
     2600    "MAD R2.xyz, R0, R2.x, R1;\n"
     2601    "ADD R1.z, R1.w, R0.w;\n"
     2602    "MAD R2.w, -R1, R0, R1.z;\n"
     2603    "ADD R1.xy, fragment.position, c[6];\n"
     2604    "MUL R1.xy, R1, c[4];\n"
     2605    "TEX R1, R1, texture[1], 2D;\n"
     2606    "ADD R2, R2, -R0;\n"
     2607    "DP4 R1.x, R1, c[7];\n"
     2608    "MAD result.color, R1.x, R2, R0;\n"
     2609    "END\n"
     2610    ;
     2611
     2612static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN =
     2613    "!!ARBfp1.0\n"
     2614    "PARAM c[11] = { program.local[0..7],\n"
     2615    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     2616    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     2617    "           { 0.33299461, 0.99999559, 1 } };\n"
     2618    "TEMP R0;\n"
     2619    "TEMP R1;\n"
     2620    "TEMP R2;\n"
     2621    "TEMP R3;\n"
     2622    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2623    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2624    "ADD R0.xyz, R0, c[3];\n"
     2625    "RCP R0.z, R0.z;\n"
     2626    "MUL R0.xy, R0, R0.z;\n"
     2627    "ABS R0.z, R0.x;\n"
     2628    "ABS R0.w, R0.y;\n"
     2629    "ADD R0.w, R0, -R0.z;\n"
     2630    "ADD R1.x, R0.y, c[8].y;\n"
     2631    "ABS R0.w, R0;\n"
     2632    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2633    "ABS R0.w, -R0.y;\n"
     2634    "MAX R1.x, R0.z, R0.w;\n"
     2635    "RCP R1.y, R1.x;\n"
     2636    "MIN R1.x, R0.z, R0.w;\n"
     2637    "MUL R1.x, R1, R1.y;\n"
     2638    "MUL R1.y, R1.x, R1.x;\n"
     2639    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     2640    "MAD R1.z, R1, R1.y, -c[9];\n"
     2641    "MAD R1.z, R1, R1.y, c[9].w;\n"
     2642    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     2643    "MAD R1.y, R1.z, R1, c[10];\n"
     2644    "MUL R1.x, R1.y, R1;\n"
     2645    "ADD R1.y, -R1.x, c[8].w;\n"
     2646    "ADD R0.z, -R0, R0.w;\n"
     2647    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2648    "ADD R0.w, -R0.z, c[8].z;\n"
     2649    "CMP R0.x, R0, R0.w, R0.z;\n"
     2650    "CMP R0.x, -R0.y, -R0, R0;\n"
     2651    "ADD R0.x, R0, c[0];\n"
     2652    "MUL R0.z, R0.x, c[8].x;\n"
     2653    "FLR R0.w, R0.z;\n"
     2654    "ADD R1.x, R0.z, -R0.w;\n"
     2655    "MUL R0.xy, fragment.position, c[5];\n"
     2656    "TEX R0, R0, texture[0], 2D;\n"
     2657    "TEX R1, R1, texture[2], 1D;\n"
     2658    "MUL R3.xyz, R1.w, R0;\n"
     2659    "MUL R2.xyz, R1, R0.w;\n"
     2660    "MAX R2.xyz, R2, R3;\n"
     2661    "ADD R2.w, -R0, c[10].z;\n"
     2662    "MAD R1.xyz, R1, R2.w, R2;\n"
     2663    "ADD R2.x, -R1.w, c[10].z;\n"
     2664    "MAD R2.xyz, R0, R2.x, R1;\n"
     2665    "ADD R1.z, R1.w, R0.w;\n"
     2666    "MAD R2.w, -R1, R0, R1.z;\n"
     2667    "ADD R1.xy, fragment.position, c[6];\n"
     2668    "MUL R1.xy, R1, c[4];\n"
     2669    "TEX R1, R1, texture[1], 2D;\n"
     2670    "ADD R2, R2, -R0;\n"
     2671    "DP4 R1.x, R1, c[7];\n"
     2672    "MAD result.color, R1.x, R2, R0;\n"
     2673    "END\n"
     2674    ;
     2675
     2676static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE =
     2677    "!!ARBfp1.0\n"
     2678    "PARAM c[11] = { program.local[0..7],\n"
     2679    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     2680    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     2681    "           { 3.141593, 0.15915494, 1, 1e-006 } };\n"
     2682    "TEMP R0;\n"
     2683    "TEMP R1;\n"
     2684    "TEMP R2;\n"
     2685    "TEMP R3;\n"
     2686    "TEMP R4;\n"
     2687    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2688    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2689    "ADD R0.xyz, R0, c[3];\n"
     2690    "RCP R0.z, R0.z;\n"
     2691    "MUL R0.xy, R0, R0.z;\n"
     2692    "ABS R0.z, R0.x;\n"
     2693    "ABS R0.w, R0.y;\n"
     2694    "ADD R0.w, R0, -R0.z;\n"
     2695    "ADD R1.x, R0.y, c[8];\n"
     2696    "ABS R0.w, R0;\n"
     2697    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2698    "ABS R0.w, -R0.y;\n"
     2699    "MAX R1.x, R0.z, R0.w;\n"
     2700    "RCP R1.y, R1.x;\n"
     2701    "MIN R1.x, R0.z, R0.w;\n"
     2702    "MUL R1.x, R1, R1.y;\n"
     2703    "MUL R1.y, R1.x, R1.x;\n"
     2704    "MAD R1.z, R1.y, c[8].y, c[8];\n"
     2705    "MAD R1.z, R1, R1.y, -c[8].w;\n"
     2706    "MAD R1.z, R1, R1.y, c[9].x;\n"
     2707    "MAD R1.z, R1, R1.y, -c[9].y;\n"
     2708    "MAD R1.y, R1.z, R1, c[9].z;\n"
     2709    "MUL R1.x, R1.y, R1;\n"
     2710    "ADD R1.y, -R1.x, c[9].w;\n"
     2711    "ADD R0.z, -R0, R0.w;\n"
     2712    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2713    "ADD R0.w, -R0.z, c[10].x;\n"
     2714    "CMP R0.x, R0, R0.w, R0.z;\n"
     2715    "CMP R0.x, -R0.y, -R0, R0;\n"
     2716    "ADD R0.x, R0, c[0];\n"
     2717    "MUL R0.x, R0, c[10].y;\n"
    26282718    "FLR R0.y, R0.x;\n"
    26292719    "ADD R0.x, R0, -R0.y;\n"
    26302720    "TEX R0, R0, texture[2], 1D;\n"
    2631     "MUL R3.xyz, R1, R0.w;\n"
    2632     "MUL R2.xyz, R0, R1.w;\n"
    2633     "MIN R2.xyz, R2, R3;\n"
    2634     "ADD R2.w, -R1, c[7];\n"
    2635     "MAD R0.xyz, R0, R2.w, R2;\n"
    2636     "ADD R2.x, -R0.w, c[7].w;\n"
    2637     "MAD R2.xyz, R1, R2.x, R0;\n"
    2638     "ADD R0.z, R0.w, R1.w;\n"
    2639     "MAD R2.w, -R0, R1, R0.z;\n"
    2640     "ADD R0.xy, fragment.position, c[0];\n"
    2641     "MUL R0.xy, R0, c[1];\n"
    2642     "TEX R0, R0, texture[1], 2D;\n"
    2643     "ADD R2, R2, -R1;\n"
    2644     "DP4 R0.x, R0, c[2];\n"
    2645     "MAD result.color, R0.x, R2, R1;\n"
    2646     "END\n"
    2647     ;
    2648 
    2649 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN =
    2650     "!!ARBfp1.0\n"
    2651     "PARAM c[11] = { program.local[0..5],\n"
    2652     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2653     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2654     "           program.local[8],\n"
    2655     "           { 0.15915494 },\n"
    2656     "           program.local[10] };\n"
    2657     "TEMP R0;\n"
    2658     "TEMP R1;\n"
    2659     "TEMP R2;\n"
    2660     "TEMP R3;\n"
    2661     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2662     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2663     "ADD R0.xyz, R0, c[5];\n"
    2664     "RCP R0.z, R0.z;\n"
    2665     "MUL R0.xy, R0, R0.z;\n"
    2666     "ABS R0.w, R0.x;\n"
    2667     "ABS R0.z, R0.y;\n"
    2668     "ADD R0.z, R0, -R0.w;\n"
    2669     "ADD R0.w, R0.y, c[6].x;\n"
    2670     "ABS R0.z, R0;\n"
    2671     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2672     "ABS R0.z, -R0.y;\n"
    2673     "ADD R0.z, R0, c[6].y;\n"
    2674     "ADD R0.w, R0.x, R0.z;\n"
    2675     "ADD R1.x, R0.z, -R0;\n"
    2676     "RCP R1.y, R0.w;\n"
     2721    "MAX R1.x, R0.w, c[10].w;\n"
    26772722    "RCP R1.x, R1.x;\n"
    2678     "MUL R0.w, R0, R1.x;\n"
    2679     "ADD R0.z, R0.x, -R0;\n"
    2680     "MUL R0.z, R0, R1.y;\n"
    2681     "CMP R0.z, R0.x, R0.w, R0;\n"
    2682     "MUL R0.w, R0.z, R0.z;\n"
    2683     "MOV R1.x, c[7].y;\n"
    2684     "CMP R0.x, R0, c[7], R1;\n"
    2685     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2686     "MUL R1.xy, fragment.position, c[10];\n"
     2723    "MAD R1.xyz, -R0, R1.x, c[10].z;\n"
     2724    "MAX R2.xyz, R1, c[10].w;\n"
     2725    "MUL R1.xy, fragment.position, c[5];\n"
    26872726    "TEX R1, R1, texture[0], 2D;\n"
    2688     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2689     "MAD R0.x, R0.w, R0.z, R0;\n"
    2690     "MAD R0.x, R0, R0.y, c[8];\n"
    2691     "MUL R0.x, R0, c[9];\n"
    2692     "FLR R0.y, R0.x;\n"
    2693     "ADD R0.x, R0, -R0.y;\n"
    2694     "TEX R0, R0, texture[2], 1D;\n"
    2695     "MUL R3.xyz, R1, R0.w;\n"
    2696     "MUL R2.xyz, R0, R1.w;\n"
    2697     "MAX R2.xyz, R2, R3;\n"
    2698     "ADD R2.w, -R1, c[7];\n"
    2699     "MAD R0.xyz, R0, R2.w, R2;\n"
    2700     "ADD R2.x, -R0.w, c[7].w;\n"
    2701     "MAD R2.xyz, R1, R2.x, R0;\n"
    2702     "ADD R0.z, R0.w, R1.w;\n"
    2703     "MAD R2.w, -R0, R1, R0.z;\n"
    2704     "ADD R0.xy, fragment.position, c[0];\n"
    2705     "MUL R0.xy, R0, c[1];\n"
    2706     "TEX R0, R0, texture[1], 2D;\n"
    2707     "ADD R2, R2, -R1;\n"
    2708     "DP4 R0.x, R0, c[2];\n"
    2709     "MAD result.color, R0.x, R2, R1;\n"
    2710     "END\n"
    2711     ;
    2712 
    2713 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE =
    2714     "!!ARBfp1.0\n"
    2715     "PARAM c[11] = { program.local[0..5],\n"
    2716     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2717     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2718     "           program.local[8],\n"
    2719     "           { 0.15915494, 1e-06 },\n"
    2720     "           program.local[10] };\n"
    2721     "TEMP R0;\n"
    2722     "TEMP R1;\n"
    2723     "TEMP R2;\n"
    2724     "TEMP R3;\n"
    2725     "TEMP R4;\n"
    2726     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2727     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2728     "ADD R0.xyz, R0, c[5];\n"
    2729     "RCP R0.z, R0.z;\n"
    2730     "MUL R0.xy, R0, R0.z;\n"
    2731     "ABS R0.w, R0.x;\n"
    2732     "ABS R0.z, R0.y;\n"
    2733     "ADD R0.z, R0, -R0.w;\n"
    2734     "ADD R0.w, R0.y, c[6].x;\n"
    2735     "ABS R0.z, R0;\n"
    2736     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2737     "ABS R0.z, -R0.y;\n"
    2738     "ADD R0.z, R0, c[6].y;\n"
    2739     "ADD R0.w, R0.x, R0.z;\n"
    2740     "ADD R1.x, R0.z, -R0;\n"
    2741     "RCP R1.y, R0.w;\n"
    2742     "RCP R1.x, R1.x;\n"
    2743     "MUL R0.w, R0, R1.x;\n"
    2744     "ADD R0.z, R0.x, -R0;\n"
    2745     "MUL R0.z, R0, R1.y;\n"
    2746     "CMP R0.z, R0.x, R0.w, R0;\n"
    2747     "MUL R0.w, R0.z, R0.z;\n"
    2748     "MOV R1.x, c[7].y;\n"
    2749     "CMP R0.x, R0, c[7], R1;\n"
    2750     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2751     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2752     "MAD R0.x, R0.w, R0.z, R0;\n"
    2753     "MAD R0.x, R0, R0.y, c[8];\n"
    2754     "MUL R0.x, R0, c[9];\n"
    2755     "FLR R0.y, R0.x;\n"
    2756     "ADD R0.x, R0, -R0.y;\n"
    2757     "TEX R0, R0, texture[2], 1D;\n"
    2758     "MAX R1.x, R0.w, c[9].y;\n"
    2759     "RCP R1.x, R1.x;\n"
    2760     "MAD R1.xyz, -R0, R1.x, c[7].w;\n"
    2761     "MAX R2.xyz, R1, c[9].y;\n"
    2762     "MUL R1.xy, fragment.position, c[10];\n"
    2763     "TEX R1, R1, texture[0], 2D;\n"
    2764     "ADD R2.w, -R0, c[7];\n"
     2727    "ADD R2.w, -R0, c[10].z;\n"
    27652728    "MUL R3.xyz, R1, R2.w;\n"
    2766     "ADD R2.w, -R1, c[7];\n"
     2729    "ADD R2.w, -R1, c[10].z;\n"
    27672730    "MAD R4.xyz, R0, R2.w, R3;\n"
    2768     "MUL R3.xyz, R1, R0.w;\n"
     2731    "MUL R3.xyz, R0.w, R1;\n"
    27692732    "MUL R2.w, R0, R1;\n"
    27702733    "MAD R0.xyz, R0, R1.w, R3;\n"
     
    27792742    "ADD R0.z, R0.w, R1.w;\n"
    27802743    "MAD R2.w, -R0, R1, R0.z;\n"
    2781     "ADD R0.xy, fragment.position, c[0];\n"
    2782     "MUL R0.xy, R0, c[1];\n"
     2744    "ADD R0.xy, fragment.position, c[6];\n"
     2745    "MUL R0.xy, R0, c[4];\n"
    27832746    "TEX R0, R0, texture[1], 2D;\n"
    27842747    "ADD R2, R2, -R1;\n"
    2785     "DP4 R0.x, R0, c[2];\n"
     2748    "DP4 R0.x, R0, c[7];\n"
    27862749    "MAD result.color, R0.x, R2, R1;\n"
    27872750    "END\n"
     
    27902753static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN =
    27912754    "!!ARBfp1.0\n"
    2792     "PARAM c[11] = { program.local[0..5],\n"
    2793     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2794     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2795     "           program.local[8],\n"
    2796     "           { 0.15915494, 9.9999997e-06 },\n"
    2797     "           program.local[10] };\n"
     2755    "PARAM c[11] = { program.local[0..7],\n"
     2756    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     2757    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     2758    "           { 3.141593, 0.15915494, 1, 9.9999997e-006 } };\n"
    27982759    "TEMP R0;\n"
    27992760    "TEMP R1;\n"
     
    28022763    "TEMP R4;\n"
    28032764    "TEMP R5;\n"
    2804     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2805     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2806     "ADD R0.xyz, R0, c[5];\n"
     2765    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2766    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2767    "ADD R0.xyz, R0, c[3];\n"
    28072768    "RCP R0.z, R0.z;\n"
    28082769    "MUL R0.xy, R0, R0.z;\n"
     
    28102771    "ABS R0.z, R0.y;\n"
    28112772    "ADD R0.z, R0, -R0.w;\n"
    2812     "ADD R0.w, R0.y, c[6].x;\n"
     2773    "ADD R1.x, R0.y, c[8];\n"
    28132774    "ABS R0.z, R0;\n"
    2814     "CMP R0.y, -R0.z, R0, R0.w;\n"
     2775    "CMP R0.y, -R0.z, R0, R1.x;\n"
    28152776    "ABS R0.z, -R0.y;\n"
    2816     "ADD R0.z, R0, c[6].y;\n"
    2817     "ADD R0.w, R0.x, R0.z;\n"
    2818     "ADD R1.x, R0.z, -R0;\n"
    2819     "RCP R1.y, R0.w;\n"
    2820     "RCP R1.x, R1.x;\n"
    2821     "MUL R0.w, R0, R1.x;\n"
    2822     "ADD R0.z, R0.x, -R0;\n"
    2823     "MUL R0.z, R0, R1.y;\n"
    2824     "CMP R0.z, R0.x, R0.w, R0;\n"
    2825     "MUL R0.w, R0.z, R0.z;\n"
    2826     "MOV R1.x, c[7].y;\n"
    2827     "CMP R0.x, R0, c[7], R1;\n"
    2828     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2829     "MUL R1.xy, fragment.position, c[10];\n"
    2830     "TEX R1, R1, texture[0], 2D;\n"
    2831     "ADD R2.w, -R1, c[7];\n"
    2832     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2833     "MAD R0.x, R0.w, R0.z, R0;\n"
    2834     "MAD R0.x, R0, R0.y, c[8];\n"
    2835     "MUL R0.x, R0, c[9];\n"
     2777    "MAX R1.x, R0.w, R0.z;\n"
     2778    "RCP R1.y, R1.x;\n"
     2779    "MIN R1.x, R0.w, R0.z;\n"
     2780    "MUL R1.x, R1, R1.y;\n"
     2781    "MUL R1.y, R1.x, R1.x;\n"
     2782    "MAD R1.z, R1.y, c[8].y, c[8];\n"
     2783    "MAD R1.z, R1, R1.y, -c[8].w;\n"
     2784    "MAD R1.z, R1, R1.y, c[9].x;\n"
     2785    "MAD R1.z, R1, R1.y, -c[9].y;\n"
     2786    "MAD R1.y, R1.z, R1, c[9].z;\n"
     2787    "MUL R1.x, R1.y, R1;\n"
     2788    "ADD R1.y, -R1.x, c[9].w;\n"
     2789    "ADD R0.z, -R0.w, R0;\n"
     2790    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2791    "ADD R0.w, -R0.z, c[10].x;\n"
     2792    "CMP R0.x, R0, R0.w, R0.z;\n"
     2793    "CMP R0.x, -R0.y, -R0, R0;\n"
     2794    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     2795    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     2796    "ADD R0.x, R0, c[0];\n"
     2797    "MUL R0.x, R0, c[10].y;\n"
    28362798    "FLR R0.y, R0.x;\n"
    28372799    "ADD R0.x, R0, -R0.y;\n"
    28382800    "TEX R0, R0, texture[2], 1D;\n"
    2839     "MUL R2.xyz, R1, R0.w;\n"
     2801    "MUL R2.xyz, R0.w, R1;\n"
    28402802    "MAD R3.xyz, R0, R1.w, R2;\n"
    28412803    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
    28422804    "MUL R4.xyz, R0.w, R2;\n"
    2843     "MAX R2.xyz, R0, c[9].y;\n"
    2844     "ADD R3.w, -R0, c[7];\n"
     2805    "MAX R2.xyz, R0, c[10].w;\n"
     2806    "ADD R2.w, -R1, c[10].z;\n"
     2807    "ADD R3.w, -R0, c[10].z;\n"
    28452808    "MUL R5.xyz, R0, R2.w;\n"
    28462809    "RCP R2.x, R2.x;\n"
     
    28572820    "ADD R0.z, R0.w, R1.w;\n"
    28582821    "MAD R2.w, -R0, R1, R0.z;\n"
    2859     "ADD R0.xy, fragment.position, c[0];\n"
    2860     "MUL R0.xy, R0, c[1];\n"
     2822    "ADD R0.xy, fragment.position, c[6];\n"
     2823    "MUL R0.xy, R0, c[4];\n"
    28612824    "TEX R0, R0, texture[1], 2D;\n"
    28622825    "ADD R2, R2, -R1;\n"
    2863     "DP4 R0.x, R0, c[2];\n"
     2826    "DP4 R0.x, R0, c[7];\n"
    28642827    "MAD result.color, R0.x, R2, R1;\n"
    28652828    "END\n"
     
    28682831static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT =
    28692832    "!!ARBfp1.0\n"
    2870     "PARAM c[11] = { program.local[0..5],\n"
    2871     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2872     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2873     "           program.local[8],\n"
    2874     "           { 0.15915494, 2 },\n"
    2875     "           program.local[10] };\n"
     2833    "PARAM c[11] = { program.local[0..7],\n"
     2834    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     2835    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     2836    "           { 3.141593, 0.15915494, 2, 1 } };\n"
    28762837    "TEMP R0;\n"
    28772838    "TEMP R1;\n"
     
    28792840    "TEMP R3;\n"
    28802841    "TEMP R4;\n"
    2881     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2882     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2883     "ADD R0.xyz, R0, c[5];\n"
    2884     "RCP R0.z, R0.z;\n"
    2885     "MUL R0.xy, R0, R0.z;\n"
    2886     "ABS R0.w, R0.x;\n"
    2887     "ABS R0.z, R0.y;\n"
    2888     "ADD R0.z, R0, -R0.w;\n"
    2889     "ADD R0.w, R0.y, c[6].x;\n"
    2890     "ABS R0.z, R0;\n"
    2891     "CMP R0.y, -R0.z, R0, R0.w;\n"
    2892     "ABS R0.z, -R0.y;\n"
    2893     "ADD R0.z, R0, c[6].y;\n"
    2894     "ADD R0.w, R0.x, R0.z;\n"
    2895     "ADD R1.x, R0.z, -R0;\n"
    2896     "RCP R1.y, R0.w;\n"
    2897     "RCP R1.x, R1.x;\n"
    2898     "MUL R0.w, R0, R1.x;\n"
    2899     "ADD R0.z, R0.x, -R0;\n"
    2900     "MUL R0.z, R0, R1.y;\n"
    2901     "CMP R0.z, R0.x, R0.w, R0;\n"
    2902     "MUL R0.w, R0.z, R0.z;\n"
    2903     "MOV R1.x, c[7].y;\n"
    2904     "CMP R0.x, R0, c[7], R1;\n"
    2905     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2906     "MUL R1.xy, fragment.position, c[10];\n"
    2907     "TEX R1, R1, texture[0], 2D;\n"
    2908     "ADD R2.w, -R1, c[7];\n"
    2909     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2910     "MAD R0.x, R0.w, R0.z, R0;\n"
    2911     "MAD R0.x, R0, R0.y, c[8];\n"
    2912     "MUL R0.x, R0, c[9];\n"
     2842    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2843    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2844    "ADD R0.xyz, R0, c[3];\n"
     2845    "RCP R0.z, R0.z;\n"
     2846    "MUL R0.xy, R0, R0.z;\n"
     2847    "ABS R0.z, R0.x;\n"
     2848    "ABS R0.w, R0.y;\n"
     2849    "ADD R0.w, R0, -R0.z;\n"
     2850    "ADD R1.x, R0.y, c[8];\n"
     2851    "ABS R0.w, R0;\n"
     2852    "CMP R0.y, -R0.w, R0, R1.x;\n"
     2853    "ABS R0.w, -R0.y;\n"
     2854    "MAX R1.x, R0.z, R0.w;\n"
     2855    "RCP R1.y, R1.x;\n"
     2856    "MIN R1.x, R0.z, R0.w;\n"
     2857    "MUL R1.x, R1, R1.y;\n"
     2858    "MUL R1.y, R1.x, R1.x;\n"
     2859    "MAD R1.z, R1.y, c[8].y, c[8];\n"
     2860    "MAD R1.z, R1, R1.y, -c[8].w;\n"
     2861    "MAD R1.z, R1, R1.y, c[9].x;\n"
     2862    "MAD R1.z, R1, R1.y, -c[9].y;\n"
     2863    "MAD R1.y, R1.z, R1, c[9].z;\n"
     2864    "MUL R1.x, R1.y, R1;\n"
     2865    "ADD R0.z, -R0, R0.w;\n"
     2866    "ADD R1.y, -R1.x, c[9].w;\n"
     2867    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2868    "ADD R0.w, -R0.z, c[10].x;\n"
     2869    "CMP R0.x, R0, R0.w, R0.z;\n"
     2870    "CMP R0.x, -R0.y, -R0, R0;\n"
     2871    "ADD R0.x, R0, c[0];\n"
     2872    "MUL R0.x, R0, c[10].y;\n"
    29132873    "FLR R0.y, R0.x;\n"
    29142874    "ADD R0.x, R0, -R0.y;\n"
    29152875    "TEX R0, R0, texture[2], 1D;\n"
     2876    "MUL R1.xy, fragment.position, c[5];\n"
     2877    "TEX R1, R1, texture[0], 2D;\n"
     2878    "ADD R2.w, -R1, c[10];\n"
    29162879    "ADD R3.xyz, R0.w, -R0;\n"
    29172880    "ADD R2.xyz, R1.w, -R1;\n"
    29182881    "MUL R2.xyz, R2, R3;\n"
    2919     "MUL R2.xyz, R2, c[9].y;\n"
     2882    "MUL R2.xyz, R2, c[10].z;\n"
    29202883    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    29212884    "MUL R4.xyz, R0, R2.w;\n"
    29222885    "MAD R2.xyz, R0, R2.w, R2;\n"
    29232886    "MUL R3.xyz, R0, R1;\n"
    2924     "ADD R2.w, -R0, c[7];\n"
    2925     "MAD R3.xyz, R3, c[9].y, R4;\n"
    2926     "MUL R0.xyz, R0, c[9].y;\n"
     2887    "ADD R2.w, -R0, c[10];\n"
     2888    "MAD R3.xyz, R3, c[10].z, R4;\n"
     2889    "MUL R0.xyz, R0, c[10].z;\n"
    29272890    "SGE R0.xyz, R0, R0.w;\n"
    29282891    "MAD R3.xyz, R1, R2.w, R3;\n"
     
    29322895    "ADD R0.z, R0.w, R1.w;\n"
    29332896    "MAD R2.w, -R0, R1, R0.z;\n"
    2934     "ADD R0.xy, fragment.position, c[0];\n"
    2935     "MUL R0.xy, R0, c[1];\n"
     2897    "ADD R0.xy, fragment.position, c[6];\n"
     2898    "MUL R0.xy, R0, c[4];\n"
    29362899    "TEX R0, R0, texture[1], 2D;\n"
    29372900    "ADD R2, R2, -R1;\n"
    2938     "DP4 R0.x, R0, c[2];\n"
     2901    "DP4 R0.x, R0, c[7];\n"
    29392902    "MAD result.color, R0.x, R2, R1;\n"
    29402903    "END\n"
     
    29432906static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT =
    29442907    "!!ARBfp1.0\n"
    2945     "PARAM c[12] = { program.local[0..5],\n"
    2946     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    2947     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    2948     "           program.local[8],\n"
    2949     "           { 0.15915494, 9.9999997e-06, 2, 8 },\n"
    2950     "           program.local[10],\n"
     2908    "PARAM c[13] = { program.local[0..7],\n"
     2909    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     2910    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     2911    "           { 3.141593, 0.15915494, 1, 2 },\n"
     2912    "           { 9.9999997e-006, 4, 16, 12 },\n"
    29512913    "           { 3 } };\n"
    29522914    "TEMP R0;\n"
     
    29572919    "TEMP R5;\n"
    29582920    "TEMP R6;\n"
    2959     "MUL R0.xyz, fragment.position.y, c[4];\n"
    2960     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    2961     "ADD R0.xyz, R0, c[5];\n"
     2921    "MUL R0.xyz, fragment.position.y, c[2];\n"
     2922    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     2923    "ADD R0.xyz, R0, c[3];\n"
    29622924    "RCP R0.z, R0.z;\n"
    29632925    "MUL R0.xy, R0, R0.z;\n"
     
    29652927    "ABS R0.z, R0.y;\n"
    29662928    "ADD R0.z, R0, -R0.w;\n"
    2967     "ADD R0.w, R0.y, c[6].x;\n"
     2929    "ADD R1.x, R0.y, c[8];\n"
    29682930    "ABS R0.z, R0;\n"
    2969     "CMP R0.y, -R0.z, R0, R0.w;\n"
     2931    "CMP R0.y, -R0.z, R0, R1.x;\n"
    29702932    "ABS R0.z, -R0.y;\n"
    2971     "ADD R0.z, R0, c[6].y;\n"
    2972     "ADD R0.w, R0.x, R0.z;\n"
    2973     "ADD R1.x, R0.z, -R0;\n"
    2974     "RCP R1.y, R0.w;\n"
    2975     "RCP R1.x, R1.x;\n"
    2976     "MUL R0.w, R0, R1.x;\n"
    2977     "ADD R0.z, R0.x, -R0;\n"
    2978     "MUL R0.z, R0, R1.y;\n"
    2979     "CMP R0.z, R0.x, R0.w, R0;\n"
    2980     "MOV R1.x, c[7].y;\n"
    2981     "MUL R0.w, R0.z, R0.z;\n"
    2982     "CMP R0.x, R0, c[7], R1;\n"
    2983     "MAD R0.w, R0, c[6].z, -c[6];\n"
    2984     "MAD R0.x, R0.w, R0.z, R0;\n"
    2985     "MUL R0.zw, fragment.position.xyxy, c[10].xyxy;\n"
     2933    "MAX R1.x, R0.w, R0.z;\n"
     2934    "RCP R1.y, R1.x;\n"
     2935    "MIN R1.x, R0.w, R0.z;\n"
     2936    "MUL R1.x, R1, R1.y;\n"
     2937    "MUL R1.y, R1.x, R1.x;\n"
     2938    "MAD R1.z, R1.y, c[8].y, c[8];\n"
     2939    "MAD R1.z, R1, R1.y, -c[8].w;\n"
     2940    "MAD R1.z, R1, R1.y, c[9].x;\n"
     2941    "MAD R1.z, R1, R1.y, -c[9].y;\n"
     2942    "MAD R1.y, R1.z, R1, c[9].z;\n"
     2943    "MUL R1.x, R1.y, R1;\n"
     2944    "ADD R1.y, -R1.x, c[9].w;\n"
     2945    "ADD R0.z, -R0.w, R0;\n"
     2946    "CMP R0.z, -R0, R1.y, R1.x;\n"
     2947    "ADD R0.w, -R0.z, c[10].x;\n"
     2948    "CMP R0.x, R0, R0.w, R0.z;\n"
     2949    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
    29862950    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    2987     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    2988     "MAD R0.x, R0, R0.y, c[8];\n"
    2989     "MUL R0.x, R0, c[9];\n"
    2990     "FLR R0.y, R0.x;\n"
    2991     "MAX R0.z, R1.w, c[9].y;\n"
    2992     "RCP R2.w, R0.z;\n"
    2993     "MUL R2.xyz, R1, R2.w;\n"
    2994     "RSQ R3.w, R2.x;\n"
    2995     "RSQ R4.y, R2.z;\n"
    2996     "RCP R4.x, R3.w;\n"
    2997     "ADD R0.x, R0, -R0.y;\n"
    2998     "TEX R0, R0, texture[2], 1D;\n"
    2999     "MAD R3.xyz, R0, c[9].z, -R0.w;\n"
    3000     "RSQ R3.w, R2.y;\n"
    3001     "RCP R4.z, R4.y;\n"
    3002     "RCP R4.y, R3.w;\n"
    3003     "MAD R4.xyz, R4, R1.w, -R1;\n"
    3004     "MUL R6.xyz, R4, R3;\n"
    3005     "MUL R4.xyz, -R2, c[9].w;\n"
    3006     "MAD R2.xyz, -R1, R2.w, c[7].w;\n"
    3007     "ADD R5.xyz, R4, c[11].x;\n"
    3008     "MUL R4.xyz, R2, R3;\n"
    3009     "MAD R4.xyz, -R4, R5, R0.w;\n"
    3010     "MAD R2.xyz, -R2, R3, R0.w;\n"
    3011     "MAD R5.xyz, R1, R0.w, R6;\n"
    3012     "MUL R4.xyz, R1, R4;\n"
    3013     "MUL R6.xyz, R1, c[9].w;\n"
    3014     "ADD R5.xyz, R5, -R4;\n"
    3015     "SGE R6.xyz, R6, R1.w;\n"
    3016     "MUL R5.xyz, R6, R5;\n"
    3017     "ADD R3.xyz, R4, R5;\n"
    3018     "MUL R2.xyz, R1, R2;\n"
    3019     "MUL R4.xyz, R0, c[9].z;\n"
    3020     "ADD R3.xyz, R3, -R2;\n"
    3021     "SGE R4.xyz, R4, R0.w;\n"
    3022     "MUL R3.xyz, R4, R3;\n"
    3023     "ADD R2.xyz, R2, R3;\n"
    3024     "ADD R2.w, -R1, c[7];\n"
    3025     "MAD R0.xyz, R0, R2.w, R2;\n"
    3026     "ADD R2.x, -R0.w, c[7].w;\n"
    3027     "MAD R2.xyz, R1, R2.x, R0;\n"
    3028     "ADD R0.z, R0.w, R1.w;\n"
    3029     "MAD R2.w, -R0, R1, R0.z;\n"
    3030     "ADD R0.xy, fragment.position, c[0];\n"
    3031     "MUL R0.xy, R0, c[1];\n"
    3032     "TEX R0, R0, texture[1], 2D;\n"
    3033     "ADD R2, R2, -R1;\n"
    3034     "DP4 R0.x, R0, c[2];\n"
    3035     "MAD result.color, R0.x, R2, R1;\n"
    3036     "END\n"
    3037     ;
    3038 
    3039 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE =
    3040     "!!ARBfp1.0\n"
    3041     "PARAM c[11] = { program.local[0..5],\n"
    3042     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3043     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3044     "           program.local[8],\n"
    3045     "           { 0.15915494, 2 },\n"
    3046     "           program.local[10] };\n"
    3047     "TEMP R0;\n"
    3048     "TEMP R1;\n"
    3049     "TEMP R2;\n"
    3050     "TEMP R3;\n"
    3051     "MUL R0.xyz, fragment.position.y, c[4];\n"
    3052     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    3053     "ADD R0.xyz, R0, c[5];\n"
    3054     "RCP R0.z, R0.z;\n"
    3055     "MUL R0.xy, R0, R0.z;\n"
    3056     "ABS R0.w, R0.x;\n"
    3057     "ABS R0.z, R0.y;\n"
    3058     "ADD R0.z, R0, -R0.w;\n"
    3059     "ADD R0.w, R0.y, c[6].x;\n"
    3060     "ABS R0.z, R0;\n"
    3061     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3062     "ABS R0.z, -R0.y;\n"
    3063     "ADD R0.z, R0, c[6].y;\n"
    3064     "ADD R0.w, R0.x, R0.z;\n"
    3065     "ADD R1.x, R0.z, -R0;\n"
    3066     "RCP R1.y, R0.w;\n"
    3067     "RCP R1.x, R1.x;\n"
    3068     "MUL R0.w, R0, R1.x;\n"
    3069     "ADD R0.z, R0.x, -R0;\n"
    3070     "MUL R0.z, R0, R1.y;\n"
    3071     "CMP R0.z, R0.x, R0.w, R0;\n"
    3072     "MUL R0.w, R0.z, R0.z;\n"
    3073     "MOV R1.x, c[7].y;\n"
    3074     "CMP R0.x, R0, c[7], R1;\n"
    3075     "MAD R0.w, R0, c[6].z, -c[6];\n"
    3076     "MAD R0.x, R0.w, R0.z, R0;\n"
    3077     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    3078     "MAD R0.x, R0, R0.y, c[8];\n"
    3079     "MUL R0.x, R0, c[9];\n"
    3080     "FLR R0.y, R0.x;\n"
    3081     "MUL R0.zw, fragment.position.xyxy, c[10].xyxy;\n"
    3082     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    3083     "ADD R0.x, R0, -R0.y;\n"
    3084     "TEX R0, R0, texture[2], 1D;\n"
    3085     "ADD R3.xyz, R0, R1;\n"
    3086     "MUL R2.xyz, R1, R0.w;\n"
    3087     "MUL R0.xyz, R0, R1.w;\n"
    3088     "MIN R0.xyz, R0, R2;\n"
    3089     "MAD R2.xyz, -R0, c[9].y, R3;\n"
    3090     "ADD R0.z, R0.w, R1.w;\n"
    3091     "MAD R2.w, -R0, R1, R0.z;\n"
    3092     "ADD R0.xy, fragment.position, c[0];\n"
    3093     "MUL R0.xy, R0, c[1];\n"
    3094     "TEX R0, R0, texture[1], 2D;\n"
    3095     "ADD R2, R2, -R1;\n"
    3096     "DP4 R0.x, R0, c[2];\n"
    3097     "MAD result.color, R0.x, R2, R1;\n"
    3098     "END\n"
    3099     ;
    3100 
    3101 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION =
    3102     "!!ARBfp1.0\n"
    3103     "PARAM c[11] = { program.local[0..5],\n"
    3104     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3105     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3106     "           program.local[8],\n"
    3107     "           { 0.15915494, 2 },\n"
    3108     "           program.local[10] };\n"
    3109     "TEMP R0;\n"
    3110     "TEMP R1;\n"
    3111     "TEMP R2;\n"
    3112     "TEMP R3;\n"
    3113     "MUL R0.xyz, fragment.position.y, c[4];\n"
    3114     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    3115     "ADD R0.xyz, R0, c[5];\n"
    3116     "RCP R0.z, R0.z;\n"
    3117     "MUL R0.xy, R0, R0.z;\n"
    3118     "ABS R0.w, R0.x;\n"
    3119     "ABS R0.z, R0.y;\n"
    3120     "ADD R0.z, R0, -R0.w;\n"
    3121     "ADD R0.w, R0.y, c[6].x;\n"
    3122     "ABS R0.z, R0;\n"
    3123     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3124     "ABS R0.z, -R0.y;\n"
    3125     "ADD R0.z, R0, c[6].y;\n"
    3126     "ADD R0.w, R0.x, R0.z;\n"
    3127     "ADD R1.x, R0.z, -R0;\n"
    3128     "RCP R1.y, R0.w;\n"
    3129     "RCP R1.x, R1.x;\n"
    3130     "MUL R0.w, R0, R1.x;\n"
    3131     "ADD R0.z, R0.x, -R0;\n"
    3132     "MUL R0.z, R0, R1.y;\n"
    3133     "CMP R0.z, R0.x, R0.w, R0;\n"
    3134     "MUL R0.w, R0.z, R0.z;\n"
    3135     "MOV R1.x, c[7].y;\n"
    3136     "CMP R0.x, R0, c[7], R1;\n"
    3137     "MAD R0.w, R0, c[6].z, -c[6];\n"
    3138     "MUL R1.xy, fragment.position, c[10];\n"
    3139     "TEX R1, R1, texture[0], 2D;\n"
    3140     "CMP R0.y, -R0, c[7].z, c[7].w;\n"
    3141     "MAD R0.x, R0.w, R0.z, R0;\n"
    3142     "MAD R0.x, R0, R0.y, c[8];\n"
    3143     "MUL R0.x, R0, c[9];\n"
     2951    "CMP R0.x, -R0.y, -R0, R0;\n"
     2952    "MAX R0.z, R1.w, c[11].x;\n"
     2953    "RCP R2.x, R0.z;\n"
     2954    "MUL R3.xyz, R1, R2.x;\n"
     2955    "MAD R4.xyz, R3, c[11].z, -c[11].w;\n"
     2956    "ADD R0.x, R0, c[0];\n"
     2957    "MUL R0.x, R0, c[10].y;\n"
    31442958    "FLR R0.y, R0.x;\n"
    31452959    "ADD R0.x, R0, -R0.y;\n"
    31462960    "TEX R0, R0, texture[2], 1D;\n"
    3147     "MUL R2.xyz, R1, R0.w;\n"
    3148     "MAD R3.xyz, R0, R1.w, R2;\n"
    3149     "MUL R2.xyz, R0, R1;\n"
    3150     "MAD R2.xyz, -R2, c[9].y, R3;\n"
    3151     "ADD R2.w, -R1, c[7];\n"
    3152     "MAD R0.xyz, R0, R2.w, R2;\n"
    3153     "ADD R2.x, -R0.w, c[7].w;\n"
    3154     "MAD R2.xyz, R1, R2.x, R0;\n"
     2961    "MAD R2.xyz, R0, c[10].w, -R0.w;\n"
     2962    "MAD R4.xyz, R3, R4, c[12].x;\n"
     2963    "MUL R5.xyz, R1.w, R2;\n"
     2964    "MUL R6.xyz, R5, R4;\n"
     2965    "RSQ R2.w, R3.x;\n"
     2966    "RCP R4.x, R2.w;\n"
     2967    "RSQ R2.w, R3.y;\n"
     2968    "RSQ R3.w, R3.z;\n"
     2969    "RCP R4.y, R2.w;\n"
     2970    "RCP R4.z, R3.w;\n"
     2971    "ADD R4.xyz, -R3, R4;\n"
     2972    "MUL R6.xyz, R3, R6;\n"
     2973    "MUL R4.xyz, R5, R4;\n"
     2974    "ADD R3.xyz, -R3, c[10].z;\n"
     2975    "MAD R2.xyz, R2, R3, R0.w;\n"
     2976    "MUL R3.xyz, R0, c[10].w;\n"
     2977    "MAD R5.xyz, R0.w, R1, R6;\n"
     2978    "MAD R4.xyz, R0.w, R1, R4;\n"
     2979    "ADD R6.xyz, R4, -R5;\n"
     2980    "MUL R4.xyz, R1, c[11].y;\n"
     2981    "SGE R4.xyz, R4, R1.w;\n"
     2982    "MAD R4.xyz, R4, R6, R5;\n"
     2983    "MAD R4.xyz, -R1, R2, R4;\n"
     2984    "SGE R3.xyz, R3, R0.w;\n"
     2985    "MUL R2.xyz, R1, R2;\n"
     2986    "ADD R2.w, -R1, c[10].z;\n"
     2987    "MAD R2.xyz, R3, R4, R2;\n"
     2988    "MAD R2.xyz, R0, R2.w, R2;\n"
     2989    "ADD R0.x, -R0.w, c[10].z;\n"
     2990    "MAD R2.xyz, R1, R0.x, R2;\n"
    31552991    "ADD R0.z, R0.w, R1.w;\n"
    31562992    "MAD R2.w, -R0, R1, R0.z;\n"
    3157     "ADD R0.xy, fragment.position, c[0];\n"
    3158     "MUL R0.xy, R0, c[1];\n"
     2993    "ADD R0.xy, fragment.position, c[6];\n"
     2994    "MUL R0.xy, R0, c[4];\n"
    31592995    "TEX R0, R0, texture[1], 2D;\n"
    31602996    "ADD R2, R2, -R1;\n"
    3161     "DP4 R0.x, R0, c[2];\n"
     2997    "DP4 R0.x, R0, c[7];\n"
    31622998    "MAD result.color, R0.x, R2, R1;\n"
    31632999    "END\n"
    31643000    ;
    31653001
     3002static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE =
     3003    "!!ARBfp1.0\n"
     3004    "PARAM c[11] = { program.local[0..7],\n"
     3005    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3006    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3007    "           { 0.33299461, 0.99999559, 2 } };\n"
     3008    "TEMP R0;\n"
     3009    "TEMP R1;\n"
     3010    "TEMP R2;\n"
     3011    "TEMP R3;\n"
     3012    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3013    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3014    "ADD R0.xyz, R0, c[3];\n"
     3015    "RCP R0.z, R0.z;\n"
     3016    "MUL R0.xy, R0, R0.z;\n"
     3017    "ABS R0.z, R0.x;\n"
     3018    "ABS R0.w, R0.y;\n"
     3019    "ADD R0.w, R0, -R0.z;\n"
     3020    "ADD R1.x, R0.y, c[8].y;\n"
     3021    "ABS R0.w, R0;\n"
     3022    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3023    "ABS R0.w, -R0.y;\n"
     3024    "MAX R1.x, R0.z, R0.w;\n"
     3025    "RCP R1.y, R1.x;\n"
     3026    "MIN R1.x, R0.z, R0.w;\n"
     3027    "MUL R1.x, R1, R1.y;\n"
     3028    "MUL R1.y, R1.x, R1.x;\n"
     3029    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     3030    "MAD R1.z, R1, R1.y, -c[9];\n"
     3031    "MAD R1.z, R1, R1.y, c[9].w;\n"
     3032    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     3033    "MAD R1.y, R1.z, R1, c[10];\n"
     3034    "MUL R1.x, R1.y, R1;\n"
     3035    "ADD R1.y, -R1.x, c[8].w;\n"
     3036    "ADD R0.z, -R0, R0.w;\n"
     3037    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3038    "ADD R0.w, -R0.z, c[8].z;\n"
     3039    "CMP R0.x, R0, R0.w, R0.z;\n"
     3040    "CMP R0.x, -R0.y, -R0, R0;\n"
     3041    "ADD R0.x, R0, c[0];\n"
     3042    "MUL R0.z, R0.x, c[8].x;\n"
     3043    "FLR R0.w, R0.z;\n"
     3044    "ADD R1.x, R0.z, -R0.w;\n"
     3045    "MUL R0.xy, fragment.position, c[5];\n"
     3046    "TEX R0, R0, texture[0], 2D;\n"
     3047    "TEX R1, R1, texture[2], 1D;\n"
     3048    "ADD R2.xyz, R1, R0;\n"
     3049    "MUL R3.xyz, R1.w, R0;\n"
     3050    "MUL R1.xyz, R1, R0.w;\n"
     3051    "MIN R1.xyz, R1, R3;\n"
     3052    "MAD R2.xyz, -R1, c[10].z, R2;\n"
     3053    "ADD R1.z, R1.w, R0.w;\n"
     3054    "MAD R2.w, -R1, R0, R1.z;\n"
     3055    "ADD R1.xy, fragment.position, c[6];\n"
     3056    "MUL R1.xy, R1, c[4];\n"
     3057    "TEX R1, R1, texture[1], 2D;\n"
     3058    "ADD R2, R2, -R0;\n"
     3059    "DP4 R1.x, R1, c[7];\n"
     3060    "MAD result.color, R1.x, R2, R0;\n"
     3061    "END\n"
     3062    ;
     3063
     3064static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION =
     3065    "!!ARBfp1.0\n"
     3066    "PARAM c[11] = { program.local[0..7],\n"
     3067    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3068    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3069    "           { 0.33299461, 0.99999559, 2, 1 } };\n"
     3070    "TEMP R0;\n"
     3071    "TEMP R1;\n"
     3072    "TEMP R2;\n"
     3073    "TEMP R3;\n"
     3074    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3075    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3076    "ADD R0.xyz, R0, c[3];\n"
     3077    "RCP R0.z, R0.z;\n"
     3078    "MUL R0.xy, R0, R0.z;\n"
     3079    "ABS R0.z, R0.x;\n"
     3080    "ABS R0.w, R0.y;\n"
     3081    "ADD R0.w, R0, -R0.z;\n"
     3082    "ADD R1.x, R0.y, c[8].y;\n"
     3083    "ABS R0.w, R0;\n"
     3084    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3085    "ABS R0.w, -R0.y;\n"
     3086    "MAX R1.x, R0.z, R0.w;\n"
     3087    "RCP R1.y, R1.x;\n"
     3088    "MIN R1.x, R0.z, R0.w;\n"
     3089    "MUL R1.x, R1, R1.y;\n"
     3090    "MUL R1.y, R1.x, R1.x;\n"
     3091    "MAD R1.z, R1.y, c[9].x, c[9].y;\n"
     3092    "MAD R1.z, R1, R1.y, -c[9];\n"
     3093    "MAD R1.z, R1, R1.y, c[9].w;\n"
     3094    "MAD R1.z, R1, R1.y, -c[10].x;\n"
     3095    "MAD R1.y, R1.z, R1, c[10];\n"
     3096    "MUL R1.x, R1.y, R1;\n"
     3097    "ADD R1.y, -R1.x, c[8].w;\n"
     3098    "ADD R0.z, -R0, R0.w;\n"
     3099    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3100    "ADD R0.w, -R0.z, c[8].z;\n"
     3101    "CMP R0.x, R0, R0.w, R0.z;\n"
     3102    "CMP R0.x, -R0.y, -R0, R0;\n"
     3103    "ADD R0.x, R0, c[0];\n"
     3104    "MUL R0.z, R0.x, c[8].x;\n"
     3105    "FLR R0.w, R0.z;\n"
     3106    "ADD R1.x, R0.z, -R0.w;\n"
     3107    "MUL R0.xy, fragment.position, c[5];\n"
     3108    "TEX R0, R0, texture[0], 2D;\n"
     3109    "TEX R1, R1, texture[2], 1D;\n"
     3110    "MUL R2.xyz, R1.w, R0;\n"
     3111    "MAD R3.xyz, R1, R0.w, R2;\n"
     3112    "MUL R2.xyz, R1, R0;\n"
     3113    "MAD R2.xyz, -R2, c[10].z, R3;\n"
     3114    "ADD R2.w, -R0, c[10];\n"
     3115    "MAD R1.xyz, R1, R2.w, R2;\n"
     3116    "ADD R2.x, -R1.w, c[10].w;\n"
     3117    "MAD R2.xyz, R0, R2.x, R1;\n"
     3118    "ADD R1.z, R1.w, R0.w;\n"
     3119    "MAD R2.w, -R1, R0, R1.z;\n"
     3120    "ADD R1.xy, fragment.position, c[6];\n"
     3121    "MUL R1.xy, R1, c[4];\n"
     3122    "TEX R1, R1, texture[1], 2D;\n"
     3123    "ADD R2, R2, -R0;\n"
     3124    "DP4 R1.x, R1, c[7];\n"
     3125    "MAD result.color, R1.x, R2, R0;\n"
     3126    "END\n"
     3127    ;
     3128
    31663129static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    31673130    "!!ARBfp1.0\n"
    3168     "PARAM c[10] = { program.local[0..2],\n"
    3169     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3170     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3171     "           program.local[5],\n"
    3172     "           { 0.15915494 },\n"
    3173     "           program.local[7..9] };\n"
    3174     "TEMP R0;\n"
    3175     "TEMP R1;\n"
    3176     "TEMP R2;\n"
    3177     "TEMP R3;\n"
    3178     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3179     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3180     "ADD R0.xyz, R0, c[2];\n"
    3181     "RCP R0.z, R0.z;\n"
    3182     "MUL R0.xy, R0, R0.z;\n"
    3183     "ABS R0.w, R0.x;\n"
    3184     "ABS R0.z, R0.y;\n"
    3185     "ADD R0.z, R0, -R0.w;\n"
    3186     "ADD R0.w, R0.y, c[3].x;\n"
    3187     "ABS R0.z, R0;\n"
    3188     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3189     "ABS R0.z, -R0.y;\n"
    3190     "ADD R0.z, R0, c[3].y;\n"
    3191     "ADD R0.w, R0.x, R0.z;\n"
    3192     "ADD R1.x, R0.z, -R0;\n"
    3193     "RCP R1.y, R0.w;\n"
    3194     "RCP R1.x, R1.x;\n"
    3195     "MUL R0.w, R0, R1.x;\n"
    3196     "ADD R0.z, R0.x, -R0;\n"
    3197     "MUL R0.z, R0, R1.y;\n"
    3198     "CMP R0.z, R0.x, R0.w, R0;\n"
    3199     "MUL R0.w, R0.z, R0.z;\n"
    3200     "MOV R1.x, c[4].y;\n"
    3201     "CMP R0.x, R0, c[4], R1;\n"
    3202     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3203     "MAD R0.x, R0.w, R0.z, R0;\n"
    3204     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3205     "MAD R0.x, R0, R0.y, c[5];\n"
    3206     "MUL R0.x, R0, c[6];\n"
     3131    "PARAM c[10] = { program.local[0..6],\n"
     3132    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3133    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3134    "           { 0.33299461, 0.99999559, 1 } };\n"
     3135    "TEMP R0;\n"
     3136    "TEMP R1;\n"
     3137    "TEMP R2;\n"
     3138    "TEMP R3;\n"
     3139    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3140    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3141    "ADD R0.xyz, R0, c[3];\n"
     3142    "RCP R0.z, R0.z;\n"
     3143    "MUL R0.xy, R0, R0.z;\n"
     3144    "ABS R0.z, R0.x;\n"
     3145    "ABS R0.w, R0.y;\n"
     3146    "ADD R0.w, R0, -R0.z;\n"
     3147    "ADD R1.x, R0.y, c[7].y;\n"
     3148    "ABS R0.w, R0;\n"
     3149    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3150    "ABS R0.w, -R0.y;\n"
     3151    "MAX R1.x, R0.z, R0.w;\n"
     3152    "RCP R1.y, R1.x;\n"
     3153    "MIN R1.x, R0.z, R0.w;\n"
     3154    "MUL R1.x, R1, R1.y;\n"
     3155    "MUL R1.y, R1.x, R1.x;\n"
     3156    "MAD R1.z, R1.y, c[8].x, c[8].y;\n"
     3157    "MAD R1.z, R1, R1.y, -c[8];\n"
     3158    "MAD R1.z, R1, R1.y, c[8].w;\n"
     3159    "MAD R1.z, R1, R1.y, -c[9].x;\n"
     3160    "MAD R1.y, R1.z, R1, c[9];\n"
     3161    "MUL R1.x, R1.y, R1;\n"
     3162    "ADD R0.z, -R0, R0.w;\n"
     3163    "ADD R1.y, -R1.x, c[7].w;\n"
     3164    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3165    "ADD R0.w, -R0.z, c[7].z;\n"
     3166    "CMP R0.x, R0, R0.w, R0.z;\n"
     3167    "CMP R0.x, -R0.y, -R0, R0;\n"
     3168    "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     3169    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3170    "MUL R2.xyz, R1, c[4].y;\n"
     3171    "ADD R0.x, R0, c[0];\n"
     3172    "MUL R0.x, R0, c[7];\n"
    32073173    "FLR R0.y, R0.x;\n"
    3208     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    3209     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    3210     "MUL R2.xyz, R1, c[9].y;\n"
    32113174    "ADD R0.x, R0, -R0.y;\n"
    32123175    "TEX R0, R0, texture[1], 1D;\n"
    3213     "MUL R3.xyz, R2, R0.w;\n"
    3214     "MUL R2.xyz, R0, c[9].x;\n"
    3215     "MAD R2.xyz, R2, R1.w, R3;\n"
    3216     "ADD R2.w, -R1, c[4];\n"
    3217     "MUL R0.xyz, R0, c[8].y;\n"
    3218     "MAD R0.xyz, R0, R2.w, R2;\n"
    3219     "ADD R2.x, -R0.w, c[4].w;\n"
    3220     "MUL R1.xyz, R1, c[8].z;\n"
    3221     "MAD result.color.xyz, R1, R2.x, R0;\n"
     3176    "MUL R3.xyz, R0.w, R2;\n"
     3177    "MUL R2.xyz, R0, c[4].x;\n"
     3178    "MAD R2.xyz, R1.w, R2, R3;\n"
     3179    "ADD R2.w, -R1, c[9].z;\n"
     3180    "MUL R0.xyz, R0, c[5].y;\n"
     3181    "MAD R0.xyz, R2.w, R0, R2;\n"
     3182    "ADD R2.x, -R0.w, c[9].z;\n"
     3183    "MUL R1.xyz, R1, c[5].z;\n"
     3184    "MAD result.color.xyz, R2.x, R1, R0;\n"
    32223185    "MUL R0.x, R0.w, R1.w;\n"
    32233186    "MUL R0.z, R1.w, R2.x;\n"
    32243187    "MUL R0.y, R0.w, R2.w;\n"
    3225     "DP3 result.color.w, R0, c[8];\n"
     3188    "DP3 result.color.w, R0, c[5];\n"
    32263189    "END\n"
    32273190    ;
     
    32293192static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_MULTIPLY_NOMASK =
    32303193    "!!ARBfp1.0\n"
    3231     "PARAM c[8] = { program.local[0..2],\n"
    3232     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3233     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3234     "           program.local[5],\n"
    3235     "           { 0.15915494 },\n"
    3236     "           program.local[7] };\n"
    3237     "TEMP R0;\n"
    3238     "TEMP R1;\n"
    3239     "TEMP R2;\n"
    3240     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3241     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3242     "ADD R0.xyz, R0, c[2];\n"
    3243     "RCP R0.z, R0.z;\n"
    3244     "MUL R0.xy, R0, R0.z;\n"
    3245     "ABS R0.w, R0.x;\n"
    3246     "ABS R0.z, R0.y;\n"
    3247     "ADD R0.z, R0, -R0.w;\n"
    3248     "ADD R0.w, R0.y, c[3].x;\n"
    3249     "ABS R0.z, R0;\n"
    3250     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3251     "ABS R0.z, -R0.y;\n"
    3252     "ADD R0.z, R0, c[3].y;\n"
    3253     "ADD R0.w, R0.x, R0.z;\n"
    3254     "ADD R1.x, R0.z, -R0;\n"
    3255     "RCP R1.y, R0.w;\n"
    3256     "RCP R1.x, R1.x;\n"
    3257     "MUL R0.w, R0, R1.x;\n"
    3258     "ADD R0.z, R0.x, -R0;\n"
    3259     "MUL R0.z, R0, R1.y;\n"
    3260     "CMP R0.z, R0.x, R0.w, R0;\n"
    3261     "MUL R0.w, R0.z, R0.z;\n"
    3262     "MOV R1.x, c[4].y;\n"
    3263     "CMP R0.x, R0, c[4], R1;\n"
    3264     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3265     "MAD R0.x, R0.w, R0.z, R0;\n"
    3266     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3267     "MAD R0.x, R0, R0.y, c[5];\n"
    3268     "MUL R0.x, R0, c[6];\n"
     3194    "PARAM c[8] = { program.local[0..4],\n"
     3195    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3196    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3197    "           { 0.33299461, 0.99999559, 1 } };\n"
     3198    "TEMP R0;\n"
     3199    "TEMP R1;\n"
     3200    "TEMP R2;\n"
     3201    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3202    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3203    "ADD R0.xyz, R0, c[3];\n"
     3204    "RCP R0.z, R0.z;\n"
     3205    "MUL R0.xy, R0, R0.z;\n"
     3206    "ABS R0.z, R0.x;\n"
     3207    "ABS R0.w, R0.y;\n"
     3208    "ADD R0.w, R0, -R0.z;\n"
     3209    "ADD R1.x, R0.y, c[5].y;\n"
     3210    "ABS R0.w, R0;\n"
     3211    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3212    "ABS R0.w, -R0.y;\n"
     3213    "MAX R1.x, R0.z, R0.w;\n"
     3214    "RCP R1.y, R1.x;\n"
     3215    "MIN R1.x, R0.z, R0.w;\n"
     3216    "MUL R1.x, R1, R1.y;\n"
     3217    "MUL R1.y, R1.x, R1.x;\n"
     3218    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3219    "MAD R1.z, R1, R1.y, -c[6];\n"
     3220    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3221    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3222    "MAD R1.y, R1.z, R1, c[7];\n"
     3223    "MUL R1.x, R1.y, R1;\n"
     3224    "ADD R0.z, -R0, R0.w;\n"
     3225    "ADD R1.y, -R1.x, c[5].w;\n"
     3226    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3227    "ADD R0.w, -R0.z, c[5].z;\n"
     3228    "CMP R0.x, R0, R0.w, R0.z;\n"
     3229    "CMP R0.x, -R0.y, -R0, R0;\n"
     3230    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3231    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3232    "ADD R0.x, R0, c[0];\n"
     3233    "MUL R0.x, R0, c[5];\n"
    32693234    "FLR R0.y, R0.x;\n"
    3270     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    3271     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    32723235    "ADD R0.x, R0, -R0.y;\n"
    32733236    "TEX R0, R0, texture[1], 1D;\n"
    3274     "ADD R2.x, -R1.w, c[4].w;\n"
     3237    "ADD R2.x, -R1.w, c[7].z;\n"
    32753238    "MUL R2.xyz, R0, R2.x;\n"
    32763239    "MAD R0.xyz, R0, R1, R2;\n"
    32773240    "ADD R2.x, R0.w, R1.w;\n"
    3278     "ADD R2.y, -R0.w, c[4].w;\n"
     3241    "ADD R2.y, -R0.w, c[7].z;\n"
    32793242    "MAD result.color.xyz, R1, R2.y, R0;\n"
    32803243    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    32843247static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SCREEN_NOMASK =
    32853248    "!!ARBfp1.0\n"
    3286     "PARAM c[8] = { program.local[0..2],\n"
    3287     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3288     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3289     "           program.local[5],\n"
    3290     "           { 0.15915494 },\n"
    3291     "           program.local[7] };\n"
    3292     "TEMP R0;\n"
    3293     "TEMP R1;\n"
    3294     "TEMP R2;\n"
    3295     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3296     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3297     "ADD R0.xyz, R0, c[2];\n"
    3298     "RCP R0.z, R0.z;\n"
    3299     "MUL R0.xy, R0, R0.z;\n"
    3300     "ABS R0.w, R0.x;\n"
    3301     "ABS R0.z, R0.y;\n"
    3302     "ADD R0.z, R0, -R0.w;\n"
    3303     "ADD R0.w, R0.y, c[3].x;\n"
    3304     "ABS R0.z, R0;\n"
    3305     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3306     "ABS R0.z, -R0.y;\n"
    3307     "ADD R0.z, R0, c[3].y;\n"
    3308     "ADD R0.w, R0.x, R0.z;\n"
    3309     "ADD R1.x, R0.z, -R0;\n"
    3310     "RCP R1.y, R0.w;\n"
    3311     "RCP R1.x, R1.x;\n"
    3312     "MUL R0.w, R0, R1.x;\n"
    3313     "ADD R0.z, R0.x, -R0;\n"
    3314     "MUL R0.z, R0, R1.y;\n"
    3315     "CMP R0.z, R0.x, R0.w, R0;\n"
    3316     "MUL R0.w, R0.z, R0.z;\n"
    3317     "MOV R1.x, c[4].y;\n"
    3318     "CMP R0.x, R0, c[4], R1;\n"
    3319     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3320     "MAD R0.x, R0.w, R0.z, R0;\n"
    3321     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3322     "MAD R0.x, R0, R0.y, c[5];\n"
    3323     "MUL R0.x, R0, c[6];\n"
     3249    "PARAM c[8] = { program.local[0..4],\n"
     3250    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3251    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3252    "           { 0.33299461, 0.99999559 } };\n"
     3253    "TEMP R0;\n"
     3254    "TEMP R1;\n"
     3255    "TEMP R2;\n"
     3256    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3257    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3258    "ADD R0.xyz, R0, c[3];\n"
     3259    "RCP R0.z, R0.z;\n"
     3260    "MUL R0.xy, R0, R0.z;\n"
     3261    "ABS R0.z, R0.x;\n"
     3262    "ABS R0.w, R0.y;\n"
     3263    "ADD R0.w, R0, -R0.z;\n"
     3264    "ADD R1.x, R0.y, c[5].y;\n"
     3265    "ABS R0.w, R0;\n"
     3266    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3267    "ABS R0.w, -R0.y;\n"
     3268    "MAX R1.x, R0.z, R0.w;\n"
     3269    "RCP R1.y, R1.x;\n"
     3270    "MIN R1.x, R0.z, R0.w;\n"
     3271    "MUL R1.x, R1, R1.y;\n"
     3272    "MUL R1.y, R1.x, R1.x;\n"
     3273    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3274    "MAD R1.z, R1, R1.y, -c[6];\n"
     3275    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3276    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3277    "MAD R1.y, R1.z, R1, c[7];\n"
     3278    "MUL R1.x, R1.y, R1;\n"
     3279    "ADD R0.z, -R0, R0.w;\n"
     3280    "ADD R1.y, -R1.x, c[5].w;\n"
     3281    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3282    "ADD R0.w, -R0.z, c[5].z;\n"
     3283    "CMP R0.x, R0, R0.w, R0.z;\n"
     3284    "CMP R0.x, -R0.y, -R0, R0;\n"
     3285    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3286    "ADD R0.x, R0, c[0];\n"
     3287    "MUL R0.x, R0, c[5];\n"
    33243288    "FLR R0.y, R0.x;\n"
    3325     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    33263289    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    33273290    "ADD R0.x, R0, -R0.y;\n"
     
    33343297static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_OVERLAY_NOMASK =
    33353298    "!!ARBfp1.0\n"
    3336     "PARAM c[8] = { program.local[0..2],\n"
    3337     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3338     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3339     "           program.local[5],\n"
    3340     "           { 0.15915494, 2 },\n"
    3341     "           program.local[7] };\n"
    3342     "TEMP R0;\n"
    3343     "TEMP R1;\n"
    3344     "TEMP R2;\n"
    3345     "TEMP R3;\n"
    3346     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3347     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3348     "ADD R0.xyz, R0, c[2];\n"
    3349     "RCP R0.z, R0.z;\n"
    3350     "MUL R0.xy, R0, R0.z;\n"
    3351     "ABS R0.w, R0.x;\n"
    3352     "ABS R0.z, R0.y;\n"
    3353     "ADD R0.z, R0, -R0.w;\n"
    3354     "ADD R0.w, R0.y, c[3].x;\n"
    3355     "ABS R0.z, R0;\n"
    3356     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3357     "ABS R0.z, -R0.y;\n"
    3358     "ADD R0.z, R0, c[3].y;\n"
    3359     "ADD R0.w, R0.x, R0.z;\n"
    3360     "ADD R1.x, R0.z, -R0;\n"
    3361     "RCP R1.y, R0.w;\n"
    3362     "RCP R1.x, R1.x;\n"
    3363     "MUL R0.w, R0, R1.x;\n"
    3364     "ADD R0.z, R0.x, -R0;\n"
    3365     "MUL R0.z, R0, R1.y;\n"
    3366     "CMP R0.z, R0.x, R0.w, R0;\n"
    3367     "MUL R0.w, R0.z, R0.z;\n"
    3368     "MOV R1.x, c[4].y;\n"
    3369     "CMP R0.x, R0, c[4], R1;\n"
    3370     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3371     "MUL R1.xy, fragment.position, c[7];\n"
    3372     "TEX R1, R1, texture[0], 2D;\n"
    3373     "ADD R2.w, -R1, c[4];\n"
    3374     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3375     "MAD R0.x, R0.w, R0.z, R0;\n"
    3376     "MAD R0.x, R0, R0.y, c[5];\n"
    3377     "MUL R0.x, R0, c[6];\n"
     3299    "PARAM c[8] = { program.local[0..4],\n"
     3300    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     3301    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     3302    "           { 3.141593, 0.15915494, 2, 1 } };\n"
     3303    "TEMP R0;\n"
     3304    "TEMP R1;\n"
     3305    "TEMP R2;\n"
     3306    "TEMP R3;\n"
     3307    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3308    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3309    "ADD R0.xyz, R0, c[3];\n"
     3310    "RCP R0.z, R0.z;\n"
     3311    "MUL R0.xy, R0, R0.z;\n"
     3312    "ABS R0.z, R0.x;\n"
     3313    "ABS R0.w, R0.y;\n"
     3314    "ADD R0.w, R0, -R0.z;\n"
     3315    "ADD R1.x, R0.y, c[5];\n"
     3316    "ABS R0.w, R0;\n"
     3317    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3318    "ABS R0.w, -R0.y;\n"
     3319    "MAX R1.x, R0.z, R0.w;\n"
     3320    "RCP R1.y, R1.x;\n"
     3321    "MIN R1.x, R0.z, R0.w;\n"
     3322    "MUL R1.x, R1, R1.y;\n"
     3323    "MUL R1.y, R1.x, R1.x;\n"
     3324    "MAD R1.z, R1.y, c[5].y, c[5];\n"
     3325    "MAD R1.z, R1, R1.y, -c[5].w;\n"
     3326    "MAD R1.z, R1, R1.y, c[6].x;\n"
     3327    "MAD R1.z, R1, R1.y, -c[6].y;\n"
     3328    "MAD R1.y, R1.z, R1, c[6].z;\n"
     3329    "MUL R1.x, R1.y, R1;\n"
     3330    "ADD R0.z, -R0, R0.w;\n"
     3331    "ADD R1.y, -R1.x, c[6].w;\n"
     3332    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3333    "ADD R0.w, -R0.z, c[7].x;\n"
     3334    "CMP R0.x, R0, R0.w, R0.z;\n"
     3335    "CMP R0.x, -R0.y, -R0, R0;\n"
     3336    "ADD R0.x, R0, c[0];\n"
     3337    "MUL R0.x, R0, c[7].y;\n"
    33783338    "FLR R0.y, R0.x;\n"
    33793339    "ADD R0.x, R0, -R0.y;\n"
    33803340    "TEX R0, R0, texture[1], 1D;\n"
     3341    "MUL R1.xy, fragment.position, c[4];\n"
     3342    "TEX R1, R1, texture[0], 2D;\n"
    33813343    "ADD R3.xyz, R0.w, -R0;\n"
    33823344    "ADD R2.xyz, R1.w, -R1;\n"
    33833345    "MUL R2.xyz, R2, R3;\n"
    3384     "MUL R2.xyz, R2, c[6].y;\n"
     3346    "ADD R2.w, -R1, c[7];\n"
     3347    "MUL R2.xyz, R2, c[7].z;\n"
    33853348    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    33863349    "MAD R2.xyz, R0, R2.w, R2;\n"
    33873350    "MUL R3.xyz, R0, R2.w;\n"
    33883351    "MUL R0.xyz, R0, R1;\n"
    3389     "ADD R2.w, -R0, c[4];\n"
    3390     "MAD R0.xyz, R0, c[6].y, R3;\n"
     3352    "ADD R2.w, -R0, c[7];\n"
     3353    "MAD R0.xyz, R0, c[7].z, R3;\n"
    33913354    "MAD R0.xyz, R1, R2.w, R0;\n"
    33923355    "MAD R2.xyz, R1, R2.w, R2;\n"
    3393     "MUL R1.xyz, R1, c[6].y;\n"
     3356    "MUL R1.xyz, R1, c[7].z;\n"
    33943357    "ADD R2.w, R0, R1;\n"
    33953358    "ADD R2.xyz, R2, -R0;\n"
     
    34023365static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DARKEN_NOMASK =
    34033366    "!!ARBfp1.0\n"
    3404     "PARAM c[8] = { program.local[0..2],\n"
    3405     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3406     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3407     "           program.local[5],\n"
    3408     "           { 0.15915494 },\n"
    3409     "           program.local[7] };\n"
    3410     "TEMP R0;\n"
    3411     "TEMP R1;\n"
    3412     "TEMP R2;\n"
    3413     "TEMP R3;\n"
    3414     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3415     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3416     "ADD R0.xyz, R0, c[2];\n"
    3417     "RCP R0.z, R0.z;\n"
    3418     "MUL R0.xy, R0, R0.z;\n"
    3419     "ABS R0.w, R0.x;\n"
    3420     "ABS R0.z, R0.y;\n"
    3421     "ADD R0.z, R0, -R0.w;\n"
    3422     "ADD R0.w, R0.y, c[3].x;\n"
    3423     "ABS R0.z, R0;\n"
    3424     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3425     "ABS R0.z, -R0.y;\n"
    3426     "ADD R0.z, R0, c[3].y;\n"
    3427     "ADD R0.w, R0.x, R0.z;\n"
    3428     "ADD R1.x, R0.z, -R0;\n"
    3429     "RCP R1.y, R0.w;\n"
    3430     "RCP R1.x, R1.x;\n"
    3431     "MUL R0.w, R0, R1.x;\n"
    3432     "ADD R0.z, R0.x, -R0;\n"
    3433     "MUL R0.z, R0, R1.y;\n"
    3434     "CMP R0.z, R0.x, R0.w, R0;\n"
    3435     "MUL R0.w, R0.z, R0.z;\n"
    3436     "MOV R1.x, c[4].y;\n"
    3437     "CMP R0.x, R0, c[4], R1;\n"
    3438     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3439     "MUL R1.xy, fragment.position, c[7];\n"
    3440     "TEX R1, R1, texture[0], 2D;\n"
    3441     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3442     "MAD R0.x, R0.w, R0.z, R0;\n"
    3443     "MAD R0.x, R0, R0.y, c[5];\n"
    3444     "MUL R0.x, R0, c[6];\n"
     3367    "PARAM c[8] = { program.local[0..4],\n"
     3368    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3369    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3370    "           { 0.33299461, 0.99999559, 1 } };\n"
     3371    "TEMP R0;\n"
     3372    "TEMP R1;\n"
     3373    "TEMP R2;\n"
     3374    "TEMP R3;\n"
     3375    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3376    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3377    "ADD R0.xyz, R0, c[3];\n"
     3378    "RCP R0.z, R0.z;\n"
     3379    "MUL R0.xy, R0, R0.z;\n"
     3380    "ABS R0.z, R0.x;\n"
     3381    "ABS R0.w, R0.y;\n"
     3382    "ADD R0.w, R0, -R0.z;\n"
     3383    "ADD R1.x, R0.y, c[5].y;\n"
     3384    "ABS R0.w, R0;\n"
     3385    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3386    "ABS R0.w, -R0.y;\n"
     3387    "MAX R1.x, R0.z, R0.w;\n"
     3388    "RCP R1.y, R1.x;\n"
     3389    "MIN R1.x, R0.z, R0.w;\n"
     3390    "MUL R1.x, R1, R1.y;\n"
     3391    "MUL R1.y, R1.x, R1.x;\n"
     3392    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3393    "MAD R1.z, R1, R1.y, -c[6];\n"
     3394    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3395    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3396    "MAD R1.y, R1.z, R1, c[7];\n"
     3397    "MUL R1.x, R1.y, R1;\n"
     3398    "ADD R0.z, -R0, R0.w;\n"
     3399    "ADD R1.y, -R1.x, c[5].w;\n"
     3400    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3401    "ADD R0.w, -R0.z, c[5].z;\n"
     3402    "CMP R0.x, R0, R0.w, R0.z;\n"
     3403    "CMP R0.x, -R0.y, -R0, R0;\n"
     3404    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3405    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3406    "ADD R0.x, R0, c[0];\n"
     3407    "MUL R0.x, R0, c[5];\n"
    34453408    "FLR R0.y, R0.x;\n"
    34463409    "ADD R0.x, R0, -R0.y;\n"
    34473410    "TEX R0, R0, texture[1], 1D;\n"
    34483411    "MUL R2.xyz, R0, R1.w;\n"
    3449     "MUL R3.xyz, R1, R0.w;\n"
     3412    "MUL R3.xyz, R0.w, R1;\n"
    34503413    "MIN R2.xyz, R2, R3;\n"
    3451     "ADD R2.w, -R1, c[4];\n"
     3414    "ADD R2.w, -R1, c[7].z;\n"
    34523415    "MAD R0.xyz, R0, R2.w, R2;\n"
    34533416    "ADD R2.x, R0.w, R1.w;\n"
    3454     "ADD R2.y, -R0.w, c[4].w;\n"
     3417    "ADD R2.y, -R0.w, c[7].z;\n"
    34553418    "MAD result.color.xyz, R1, R2.y, R0;\n"
    34563419    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    34603423static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_LIGHTEN_NOMASK =
    34613424    "!!ARBfp1.0\n"
    3462     "PARAM c[8] = { program.local[0..2],\n"
    3463     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3464     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3465     "           program.local[5],\n"
    3466     "           { 0.15915494 },\n"
    3467     "           program.local[7] };\n"
    3468     "TEMP R0;\n"
    3469     "TEMP R1;\n"
    3470     "TEMP R2;\n"
    3471     "TEMP R3;\n"
    3472     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3473     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3474     "ADD R0.xyz, R0, c[2];\n"
    3475     "RCP R0.z, R0.z;\n"
    3476     "MUL R0.xy, R0, R0.z;\n"
    3477     "ABS R0.w, R0.x;\n"
    3478     "ABS R0.z, R0.y;\n"
    3479     "ADD R0.z, R0, -R0.w;\n"
    3480     "ADD R0.w, R0.y, c[3].x;\n"
    3481     "ABS R0.z, R0;\n"
    3482     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3483     "ABS R0.z, -R0.y;\n"
    3484     "ADD R0.z, R0, c[3].y;\n"
    3485     "ADD R0.w, R0.x, R0.z;\n"
    3486     "ADD R1.x, R0.z, -R0;\n"
    3487     "RCP R1.y, R0.w;\n"
    3488     "RCP R1.x, R1.x;\n"
    3489     "MUL R0.w, R0, R1.x;\n"
    3490     "ADD R0.z, R0.x, -R0;\n"
    3491     "MUL R0.z, R0, R1.y;\n"
    3492     "CMP R0.z, R0.x, R0.w, R0;\n"
    3493     "MUL R0.w, R0.z, R0.z;\n"
    3494     "MOV R1.x, c[4].y;\n"
    3495     "CMP R0.x, R0, c[4], R1;\n"
    3496     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3497     "MUL R1.xy, fragment.position, c[7];\n"
    3498     "TEX R1, R1, texture[0], 2D;\n"
    3499     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3500     "MAD R0.x, R0.w, R0.z, R0;\n"
    3501     "MAD R0.x, R0, R0.y, c[5];\n"
    3502     "MUL R0.x, R0, c[6];\n"
     3425    "PARAM c[8] = { program.local[0..4],\n"
     3426    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3427    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3428    "           { 0.33299461, 0.99999559, 1 } };\n"
     3429    "TEMP R0;\n"
     3430    "TEMP R1;\n"
     3431    "TEMP R2;\n"
     3432    "TEMP R3;\n"
     3433    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3434    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3435    "ADD R0.xyz, R0, c[3];\n"
     3436    "RCP R0.z, R0.z;\n"
     3437    "MUL R0.xy, R0, R0.z;\n"
     3438    "ABS R0.z, R0.x;\n"
     3439    "ABS R0.w, R0.y;\n"
     3440    "ADD R0.w, R0, -R0.z;\n"
     3441    "ADD R1.x, R0.y, c[5].y;\n"
     3442    "ABS R0.w, R0;\n"
     3443    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3444    "ABS R0.w, -R0.y;\n"
     3445    "MAX R1.x, R0.z, R0.w;\n"
     3446    "RCP R1.y, R1.x;\n"
     3447    "MIN R1.x, R0.z, R0.w;\n"
     3448    "MUL R1.x, R1, R1.y;\n"
     3449    "MUL R1.y, R1.x, R1.x;\n"
     3450    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3451    "MAD R1.z, R1, R1.y, -c[6];\n"
     3452    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3453    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3454    "MAD R1.y, R1.z, R1, c[7];\n"
     3455    "MUL R1.x, R1.y, R1;\n"
     3456    "ADD R0.z, -R0, R0.w;\n"
     3457    "ADD R1.y, -R1.x, c[5].w;\n"
     3458    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3459    "ADD R0.w, -R0.z, c[5].z;\n"
     3460    "CMP R0.x, R0, R0.w, R0.z;\n"
     3461    "CMP R0.x, -R0.y, -R0, R0;\n"
     3462    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3463    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3464    "ADD R0.x, R0, c[0];\n"
     3465    "MUL R0.x, R0, c[5];\n"
    35033466    "FLR R0.y, R0.x;\n"
    35043467    "ADD R0.x, R0, -R0.y;\n"
    35053468    "TEX R0, R0, texture[1], 1D;\n"
    35063469    "MUL R2.xyz, R0, R1.w;\n"
    3507     "MUL R3.xyz, R1, R0.w;\n"
     3470    "MUL R3.xyz, R0.w, R1;\n"
    35083471    "MAX R2.xyz, R2, R3;\n"
    3509     "ADD R2.w, -R1, c[4];\n"
     3472    "ADD R2.w, -R1, c[7].z;\n"
    35103473    "MAD R0.xyz, R0, R2.w, R2;\n"
    35113474    "ADD R2.x, R0.w, R1.w;\n"
    3512     "ADD R2.y, -R0.w, c[4].w;\n"
     3475    "ADD R2.y, -R0.w, c[7].z;\n"
    35133476    "MAD result.color.xyz, R1, R2.y, R0;\n"
    35143477    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    35183481static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORDODGE_NOMASK =
    35193482    "!!ARBfp1.0\n"
    3520     "PARAM c[8] = { program.local[0..2],\n"
    3521     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3522     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3523     "           program.local[5],\n"
    3524     "           { 0.15915494, 1e-06 },\n"
    3525     "           program.local[7] };\n"
    3526     "TEMP R0;\n"
    3527     "TEMP R1;\n"
    3528     "TEMP R2;\n"
    3529     "TEMP R3;\n"
    3530     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3531     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3532     "ADD R0.xyz, R0, c[2];\n"
    3533     "RCP R0.z, R0.z;\n"
    3534     "MUL R0.xy, R0, R0.z;\n"
    3535     "ABS R0.w, R0.x;\n"
    3536     "ABS R0.z, R0.y;\n"
    3537     "ADD R0.z, R0, -R0.w;\n"
    3538     "ADD R0.w, R0.y, c[3].x;\n"
    3539     "ABS R0.z, R0;\n"
    3540     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3541     "ABS R0.z, -R0.y;\n"
    3542     "ADD R0.z, R0, c[3].y;\n"
    3543     "ADD R0.w, R0.x, R0.z;\n"
    3544     "ADD R1.x, R0.z, -R0;\n"
    3545     "RCP R1.y, R0.w;\n"
    3546     "RCP R1.x, R1.x;\n"
    3547     "MUL R0.w, R0, R1.x;\n"
    3548     "ADD R0.z, R0.x, -R0;\n"
    3549     "MUL R0.z, R0, R1.y;\n"
    3550     "CMP R0.z, R0.x, R0.w, R0;\n"
    3551     "MUL R0.w, R0.z, R0.z;\n"
    3552     "MOV R1.x, c[4].y;\n"
    3553     "CMP R0.x, R0, c[4], R1;\n"
    3554     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3555     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3556     "MAD R0.x, R0.w, R0.z, R0;\n"
    3557     "MAD R0.x, R0, R0.y, c[5];\n"
    3558     "MUL R0.x, R0, c[6];\n"
     3483    "PARAM c[8] = { program.local[0..4],\n"
     3484    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     3485    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     3486    "           { 3.141593, 0.15915494, 1, 1e-006 } };\n"
     3487    "TEMP R0;\n"
     3488    "TEMP R1;\n"
     3489    "TEMP R2;\n"
     3490    "TEMP R3;\n"
     3491    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3492    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3493    "ADD R0.xyz, R0, c[3];\n"
     3494    "RCP R0.z, R0.z;\n"
     3495    "MUL R0.xy, R0, R0.z;\n"
     3496    "ABS R0.z, R0.x;\n"
     3497    "ABS R0.w, R0.y;\n"
     3498    "ADD R0.w, R0, -R0.z;\n"
     3499    "ADD R1.x, R0.y, c[5];\n"
     3500    "ABS R0.w, R0;\n"
     3501    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3502    "ABS R0.w, -R0.y;\n"
     3503    "MAX R1.x, R0.z, R0.w;\n"
     3504    "RCP R1.y, R1.x;\n"
     3505    "MIN R1.x, R0.z, R0.w;\n"
     3506    "MUL R1.x, R1, R1.y;\n"
     3507    "MUL R1.y, R1.x, R1.x;\n"
     3508    "MAD R1.z, R1.y, c[5].y, c[5];\n"
     3509    "MAD R1.z, R1, R1.y, -c[5].w;\n"
     3510    "MAD R1.z, R1, R1.y, c[6].x;\n"
     3511    "MAD R1.z, R1, R1.y, -c[6].y;\n"
     3512    "MAD R1.y, R1.z, R1, c[6].z;\n"
     3513    "MUL R1.x, R1.y, R1;\n"
     3514    "ADD R1.y, -R1.x, c[6].w;\n"
     3515    "ADD R0.z, -R0, R0.w;\n"
     3516    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3517    "ADD R0.w, -R0.z, c[7].x;\n"
     3518    "CMP R0.x, R0, R0.w, R0.z;\n"
     3519    "CMP R0.x, -R0.y, -R0, R0;\n"
     3520    "ADD R0.x, R0, c[0];\n"
     3521    "MUL R0.x, R0, c[7].y;\n"
    35593522    "FLR R0.y, R0.x;\n"
    35603523    "ADD R0.x, R0, -R0.y;\n"
    35613524    "TEX R0, R0, texture[1], 1D;\n"
    3562     "MAX R1.x, R0.w, c[6].y;\n"
     3525    "MAX R1.x, R0.w, c[7].w;\n"
    35633526    "RCP R1.x, R1.x;\n"
    3564     "MAD R1.xyz, -R0, R1.x, c[4].w;\n"
    3565     "MAX R2.xyz, R1, c[6].y;\n"
    3566     "MUL R1.xy, fragment.position, c[7];\n"
     3527    "MAD R1.xyz, -R0, R1.x, c[7].z;\n"
     3528    "MAX R2.xyz, R1, c[7].w;\n"
     3529    "MUL R1.xy, fragment.position, c[4];\n"
    35673530    "TEX R1, R1, texture[0], 2D;\n"
    3568     "ADD R2.w, -R0, c[4];\n"
     3531    "ADD R2.w, -R0, c[7].z;\n"
    35693532    "MUL R3.xyz, R1, R2.w;\n"
    3570     "ADD R2.w, -R1, c[4];\n"
     3533    "ADD R2.w, -R1, c[7].z;\n"
    35713534    "MAD R3.xyz, R0, R2.w, R3;\n"
    3572     "MUL R1.xyz, R1, R0.w;\n"
     3535    "MUL R1.xyz, R0.w, R1;\n"
    35733536    "MAD R0.xyz, R0, R1.w, R1;\n"
    35743537    "MUL R2.w, R0, R1;\n"
     
    35883551static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_COLORBURN_NOMASK =
    35893552    "!!ARBfp1.0\n"
    3590     "PARAM c[8] = { program.local[0..2],\n"
    3591     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3592     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3593     "           program.local[5],\n"
    3594     "           { 0.15915494, 9.9999997e-06 },\n"
    3595     "           program.local[7] };\n"
     3553    "PARAM c[8] = { program.local[0..4],\n"
     3554    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     3555    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     3556    "           { 3.141593, 0.15915494, 1, 9.9999997e-006 } };\n"
    35963557    "TEMP R0;\n"
    35973558    "TEMP R1;\n"
     
    36003561    "TEMP R4;\n"
    36013562    "TEMP R5;\n"
    3602     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3603     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3604     "ADD R0.xyz, R0, c[2];\n"
     3563    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3564    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3565    "ADD R0.xyz, R0, c[3];\n"
    36053566    "RCP R0.z, R0.z;\n"
    36063567    "MUL R0.xy, R0, R0.z;\n"
     
    36083569    "ABS R0.z, R0.y;\n"
    36093570    "ADD R0.z, R0, -R0.w;\n"
    3610     "ADD R0.w, R0.y, c[3].x;\n"
     3571    "ADD R1.x, R0.y, c[5];\n"
    36113572    "ABS R0.z, R0;\n"
    3612     "CMP R0.y, -R0.z, R0, R0.w;\n"
     3573    "CMP R0.y, -R0.z, R0, R1.x;\n"
    36133574    "ABS R0.z, -R0.y;\n"
    3614     "ADD R0.z, R0, c[3].y;\n"
    3615     "ADD R0.w, R0.x, R0.z;\n"
    3616     "ADD R1.x, R0.z, -R0;\n"
    3617     "RCP R1.y, R0.w;\n"
    3618     "RCP R1.x, R1.x;\n"
    3619     "MUL R0.w, R0, R1.x;\n"
    3620     "ADD R0.z, R0.x, -R0;\n"
    3621     "MUL R0.z, R0, R1.y;\n"
    3622     "CMP R0.z, R0.x, R0.w, R0;\n"
    3623     "MUL R0.w, R0.z, R0.z;\n"
    3624     "MOV R1.x, c[4].y;\n"
    3625     "CMP R0.x, R0, c[4], R1;\n"
    3626     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3627     "MUL R1.xy, fragment.position, c[7];\n"
    3628     "TEX R1, R1, texture[0], 2D;\n"
    3629     "ADD R2.w, -R1, c[4];\n"
    3630     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3631     "MAD R0.x, R0.w, R0.z, R0;\n"
    3632     "MAD R0.x, R0, R0.y, c[5];\n"
    3633     "MUL R0.x, R0, c[6];\n"
     3575    "MAX R1.x, R0.w, R0.z;\n"
     3576    "RCP R1.y, R1.x;\n"
     3577    "MIN R1.x, R0.w, R0.z;\n"
     3578    "MUL R1.x, R1, R1.y;\n"
     3579    "MUL R1.y, R1.x, R1.x;\n"
     3580    "MAD R1.z, R1.y, c[5].y, c[5];\n"
     3581    "MAD R1.z, R1, R1.y, -c[5].w;\n"
     3582    "MAD R1.z, R1, R1.y, c[6].x;\n"
     3583    "MAD R1.z, R1, R1.y, -c[6].y;\n"
     3584    "MAD R1.y, R1.z, R1, c[6].z;\n"
     3585    "MUL R1.x, R1.y, R1;\n"
     3586    "ADD R1.y, -R1.x, c[6].w;\n"
     3587    "ADD R0.z, -R0.w, R0;\n"
     3588    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3589    "ADD R0.w, -R0.z, c[7].x;\n"
     3590    "CMP R0.x, R0, R0.w, R0.z;\n"
     3591    "CMP R0.x, -R0.y, -R0, R0;\n"
     3592    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3593    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3594    "ADD R0.x, R0, c[0];\n"
     3595    "MUL R0.x, R0, c[7].y;\n"
    36343596    "FLR R0.y, R0.x;\n"
    36353597    "ADD R0.x, R0, -R0.y;\n"
    36363598    "TEX R0, R0, texture[1], 1D;\n"
    3637     "MUL R2.xyz, R1, R0.w;\n"
     3599    "MUL R2.xyz, R0.w, R1;\n"
    36383600    "MAD R3.xyz, R0, R1.w, R2;\n"
     3601    "ADD R2.w, -R1, c[7].z;\n"
    36393602    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
    36403603    "MUL R4.xyz, R0.w, R2;\n"
    3641     "MAX R2.xyz, R0, c[6].y;\n"
     3604    "MAX R2.xyz, R0, c[7].w;\n"
    36423605    "MUL R5.xyz, R0, R2.w;\n"
    3643     "ADD R3.w, -R0, c[4];\n"
     3606    "ADD R3.w, -R0, c[7].z;\n"
    36443607    "RCP R2.x, R2.x;\n"
    36453608    "RCP R2.y, R2.y;\n"
     
    36603623static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_HARDLIGHT_NOMASK =
    36613624    "!!ARBfp1.0\n"
    3662     "PARAM c[8] = { program.local[0..2],\n"
    3663     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3664     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3665     "           program.local[5],\n"
    3666     "           { 0.15915494, 2 },\n"
    3667     "           program.local[7] };\n"
     3625    "PARAM c[8] = { program.local[0..4],\n"
     3626    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     3627    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     3628    "           { 3.141593, 0.15915494, 2, 1 } };\n"
    36683629    "TEMP R0;\n"
    36693630    "TEMP R1;\n"
     
    36713632    "TEMP R3;\n"
    36723633    "TEMP R4;\n"
    3673     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3674     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3675     "ADD R0.xyz, R0, c[2];\n"
    3676     "RCP R0.z, R0.z;\n"
    3677     "MUL R0.xy, R0, R0.z;\n"
    3678     "ABS R0.w, R0.x;\n"
    3679     "ABS R0.z, R0.y;\n"
    3680     "ADD R0.z, R0, -R0.w;\n"
    3681     "ADD R0.w, R0.y, c[3].x;\n"
    3682     "ABS R0.z, R0;\n"
    3683     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3684     "ABS R0.z, -R0.y;\n"
    3685     "ADD R0.z, R0, c[3].y;\n"
    3686     "ADD R0.w, R0.x, R0.z;\n"
    3687     "ADD R1.x, R0.z, -R0;\n"
    3688     "RCP R1.y, R0.w;\n"
    3689     "RCP R1.x, R1.x;\n"
    3690     "MUL R0.w, R0, R1.x;\n"
    3691     "ADD R0.z, R0.x, -R0;\n"
    3692     "MUL R0.z, R0, R1.y;\n"
    3693     "CMP R0.z, R0.x, R0.w, R0;\n"
    3694     "MUL R0.w, R0.z, R0.z;\n"
    3695     "MOV R1.x, c[4].y;\n"
    3696     "CMP R0.x, R0, c[4], R1;\n"
    3697     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3698     "MUL R1.xy, fragment.position, c[7];\n"
    3699     "TEX R1, R1, texture[0], 2D;\n"
    3700     "ADD R2.w, -R1, c[4];\n"
    3701     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3702     "MAD R0.x, R0.w, R0.z, R0;\n"
    3703     "MAD R0.x, R0, R0.y, c[5];\n"
    3704     "MUL R0.x, R0, c[6];\n"
     3634    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3635    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3636    "ADD R0.xyz, R0, c[3];\n"
     3637    "RCP R0.z, R0.z;\n"
     3638    "MUL R0.xy, R0, R0.z;\n"
     3639    "ABS R0.z, R0.x;\n"
     3640    "ABS R0.w, R0.y;\n"
     3641    "ADD R0.w, R0, -R0.z;\n"
     3642    "ADD R1.x, R0.y, c[5];\n"
     3643    "ABS R0.w, R0;\n"
     3644    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3645    "ABS R0.w, -R0.y;\n"
     3646    "MAX R1.x, R0.z, R0.w;\n"
     3647    "RCP R1.y, R1.x;\n"
     3648    "MIN R1.x, R0.z, R0.w;\n"
     3649    "MUL R1.x, R1, R1.y;\n"
     3650    "MUL R1.y, R1.x, R1.x;\n"
     3651    "MAD R1.z, R1.y, c[5].y, c[5];\n"
     3652    "MAD R1.z, R1, R1.y, -c[5].w;\n"
     3653    "MAD R1.z, R1, R1.y, c[6].x;\n"
     3654    "MAD R1.z, R1, R1.y, -c[6].y;\n"
     3655    "MAD R1.y, R1.z, R1, c[6].z;\n"
     3656    "MUL R1.x, R1.y, R1;\n"
     3657    "ADD R0.z, -R0, R0.w;\n"
     3658    "ADD R1.y, -R1.x, c[6].w;\n"
     3659    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3660    "ADD R0.w, -R0.z, c[7].x;\n"
     3661    "CMP R0.x, R0, R0.w, R0.z;\n"
     3662    "CMP R0.x, -R0.y, -R0, R0;\n"
     3663    "ADD R0.x, R0, c[0];\n"
     3664    "MUL R0.x, R0, c[7].y;\n"
    37053665    "FLR R0.y, R0.x;\n"
    37063666    "ADD R0.x, R0, -R0.y;\n"
    37073667    "TEX R0, R0, texture[1], 1D;\n"
     3668    "MUL R1.xy, fragment.position, c[4];\n"
     3669    "TEX R1, R1, texture[0], 2D;\n"
     3670    "ADD R2.w, -R1, c[7];\n"
    37083671    "ADD R3.xyz, R0.w, -R0;\n"
    37093672    "ADD R2.xyz, R1.w, -R1;\n"
    37103673    "MUL R2.xyz, R2, R3;\n"
    3711     "MUL R2.xyz, R2, c[6].y;\n"
     3674    "MUL R2.xyz, R2, c[7].z;\n"
    37123675    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
    37133676    "MUL R4.xyz, R0, R2.w;\n"
    37143677    "MUL R3.xyz, R0, R1;\n"
    37153678    "MAD R2.xyz, R0, R2.w, R2;\n"
    3716     "ADD R2.w, -R0, c[4];\n"
    3717     "MUL R0.xyz, R0, c[6].y;\n"
     3679    "ADD R2.w, -R0, c[7];\n"
     3680    "MUL R0.xyz, R0, c[7].z;\n"
    37183681    "MAD R2.xyz, R1, R2.w, R2;\n"
    3719     "MAD R3.xyz, R3, c[6].y, R4;\n"
     3682    "MAD R3.xyz, R3, c[7].z, R4;\n"
    37203683    "MAD R1.xyz, R1, R2.w, R3;\n"
    37213684    "ADD R2.w, R0, R1;\n"
     
    37293692static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_SOFTLIGHT_NOMASK =
    37303693    "!!ARBfp1.0\n"
    3731     "PARAM c[9] = { program.local[0..2],\n"
    3732     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3733     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3734     "           program.local[5],\n"
    3735     "           { 0.15915494, 9.9999997e-06, 2, 8 },\n"
    3736     "           program.local[7],\n"
     3694    "PARAM c[10] = { program.local[0..4],\n"
     3695    "           { 0.0020000001, -0.01348047, 0.05747731, 0.1212391 },\n"
     3696    "           { 0.1956359, 0.33299461, 0.99999559, 1.570796 },\n"
     3697    "           { 3.141593, 0.15915494, 1, 2 },\n"
     3698    "           { 9.9999997e-006, 4, 16, 12 },\n"
    37373699    "           { 3 } };\n"
    37383700    "TEMP R0;\n"
     
    37433705    "TEMP R5;\n"
    37443706    "TEMP R6;\n"
    3745     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3746     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3747     "ADD R0.xyz, R0, c[2];\n"
     3707    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3708    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3709    "ADD R0.xyz, R0, c[3];\n"
    37483710    "RCP R0.z, R0.z;\n"
    37493711    "MUL R0.xy, R0, R0.z;\n"
     
    37513713    "ABS R0.z, R0.y;\n"
    37523714    "ADD R0.z, R0, -R0.w;\n"
    3753     "ADD R0.w, R0.y, c[3].x;\n"
     3715    "ADD R1.x, R0.y, c[5];\n"
    37543716    "ABS R0.z, R0;\n"
    3755     "CMP R0.y, -R0.z, R0, R0.w;\n"
     3717    "CMP R0.y, -R0.z, R0, R1.x;\n"
    37563718    "ABS R0.z, -R0.y;\n"
    3757     "ADD R0.z, R0, c[3].y;\n"
    3758     "ADD R0.w, R0.x, R0.z;\n"
    3759     "ADD R1.x, R0.z, -R0;\n"
    3760     "RCP R1.y, R0.w;\n"
    3761     "RCP R1.x, R1.x;\n"
    3762     "MUL R0.w, R0, R1.x;\n"
    3763     "ADD R0.z, R0.x, -R0;\n"
    3764     "MUL R0.z, R0, R1.y;\n"
    3765     "CMP R0.z, R0.x, R0.w, R0;\n"
    3766     "MOV R1.x, c[4].y;\n"
    3767     "MUL R0.w, R0.z, R0.z;\n"
    3768     "CMP R0.x, R0, c[4], R1;\n"
    3769     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3770     "MAD R0.x, R0.w, R0.z, R0;\n"
    3771     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
     3719    "MAX R1.x, R0.w, R0.z;\n"
     3720    "RCP R1.y, R1.x;\n"
     3721    "MIN R1.x, R0.w, R0.z;\n"
     3722    "MUL R1.x, R1, R1.y;\n"
     3723    "MUL R1.y, R1.x, R1.x;\n"
     3724    "MAD R1.z, R1.y, c[5].y, c[5];\n"
     3725    "MAD R1.z, R1, R1.y, -c[5].w;\n"
     3726    "MAD R1.z, R1, R1.y, c[6].x;\n"
     3727    "MAD R1.z, R1, R1.y, -c[6].y;\n"
     3728    "MAD R1.y, R1.z, R1, c[6].z;\n"
     3729    "MUL R1.x, R1.y, R1;\n"
     3730    "ADD R1.y, -R1.x, c[6].w;\n"
     3731    "ADD R0.z, -R0.w, R0;\n"
     3732    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3733    "ADD R0.w, -R0.z, c[7].x;\n"
     3734    "CMP R0.x, R0, R0.w, R0.z;\n"
     3735    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    37723736    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    3773     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3774     "MAD R0.x, R0, R0.y, c[5];\n"
    3775     "MUL R0.x, R0, c[6];\n"
    3776     "FLR R0.y, R0.x;\n"
    3777     "MAX R0.z, R1.w, c[6].y;\n"
    3778     "RCP R2.w, R0.z;\n"
    3779     "MUL R2.xyz, R1, R2.w;\n"
    3780     "RSQ R3.w, R2.x;\n"
    3781     "RSQ R4.y, R2.z;\n"
    3782     "RCP R4.x, R3.w;\n"
    3783     "ADD R0.x, R0, -R0.y;\n"
    3784     "TEX R0, R0, texture[1], 1D;\n"
    3785     "MAD R3.xyz, R0, c[6].z, -R0.w;\n"
    3786     "RSQ R3.w, R2.y;\n"
    3787     "RCP R4.z, R4.y;\n"
    3788     "RCP R4.y, R3.w;\n"
    3789     "MAD R4.xyz, R4, R1.w, -R1;\n"
    3790     "MUL R6.xyz, R4, R3;\n"
    3791     "MUL R4.xyz, -R2, c[6].w;\n"
    3792     "MAD R2.xyz, -R1, R2.w, c[4].w;\n"
    3793     "ADD R5.xyz, R4, c[8].x;\n"
    3794     "MUL R4.xyz, R2, R3;\n"
    3795     "MAD R4.xyz, -R4, R5, R0.w;\n"
    3796     "MAD R2.xyz, -R2, R3, R0.w;\n"
    3797     "MAD R5.xyz, R1, R0.w, R6;\n"
    3798     "MUL R4.xyz, R1, R4;\n"
    3799     "MUL R6.xyz, R1, c[6].w;\n"
    3800     "ADD R5.xyz, R5, -R4;\n"
    3801     "SGE R6.xyz, R6, R1.w;\n"
    3802     "MUL R5.xyz, R6, R5;\n"
    3803     "ADD R3.xyz, R4, R5;\n"
    3804     "MUL R2.xyz, R1, R2;\n"
    3805     "MUL R4.xyz, R0, c[6].z;\n"
    3806     "ADD R3.xyz, R3, -R2;\n"
    3807     "SGE R4.xyz, R4, R0.w;\n"
    3808     "MUL R3.xyz, R4, R3;\n"
    3809     "ADD R2.xyz, R2, R3;\n"
    3810     "ADD R2.w, -R1, c[4];\n"
    3811     "MAD R0.xyz, R0, R2.w, R2;\n"
    3812     "ADD R2.x, R0.w, R1.w;\n"
    3813     "ADD R2.y, -R0.w, c[4].w;\n"
    3814     "MAD result.color.xyz, R1, R2.y, R0;\n"
    3815     "MAD result.color.w, -R0, R1, R2.x;\n"
    3816     "END\n"
    3817     ;
    3818 
    3819 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE_NOMASK =
    3820     "!!ARBfp1.0\n"
    3821     "PARAM c[8] = { program.local[0..2],\n"
    3822     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3823     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3824     "           program.local[5],\n"
    3825     "           { 0.15915494, 2 },\n"
    3826     "           program.local[7] };\n"
    3827     "TEMP R0;\n"
    3828     "TEMP R1;\n"
    3829     "TEMP R2;\n"
    3830     "TEMP R3;\n"
    3831     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3832     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3833     "ADD R0.xyz, R0, c[2];\n"
    3834     "RCP R0.z, R0.z;\n"
    3835     "MUL R0.xy, R0, R0.z;\n"
    3836     "ABS R0.w, R0.x;\n"
    3837     "ABS R0.z, R0.y;\n"
    3838     "ADD R0.z, R0, -R0.w;\n"
    3839     "ADD R0.w, R0.y, c[3].x;\n"
    3840     "ABS R0.z, R0;\n"
    3841     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3842     "ABS R0.z, -R0.y;\n"
    3843     "ADD R0.z, R0, c[3].y;\n"
    3844     "ADD R0.w, R0.x, R0.z;\n"
    3845     "ADD R1.x, R0.z, -R0;\n"
    3846     "RCP R1.y, R0.w;\n"
    3847     "RCP R1.x, R1.x;\n"
    3848     "MUL R0.w, R0, R1.x;\n"
    3849     "ADD R0.z, R0.x, -R0;\n"
    3850     "MUL R0.z, R0, R1.y;\n"
    3851     "CMP R0.z, R0.x, R0.w, R0;\n"
    3852     "MUL R0.w, R0.z, R0.z;\n"
    3853     "MOV R1.x, c[4].y;\n"
    3854     "CMP R0.x, R0, c[4], R1;\n"
    3855     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3856     "MUL R1.xy, fragment.position, c[7];\n"
    3857     "TEX R1, R1, texture[0], 2D;\n"
    3858     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3859     "MAD R0.x, R0.w, R0.z, R0;\n"
    3860     "MAD R0.x, R0, R0.y, c[5];\n"
    3861     "MUL R0.x, R0, c[6];\n"
     3737    "CMP R0.x, -R0.y, -R0, R0;\n"
     3738    "MAX R0.z, R1.w, c[8].x;\n"
     3739    "RCP R2.x, R0.z;\n"
     3740    "MUL R3.xyz, R1, R2.x;\n"
     3741    "MAD R4.xyz, R3, c[8].z, -c[8].w;\n"
     3742    "ADD R0.x, R0, c[0];\n"
     3743    "MUL R0.x, R0, c[7].y;\n"
    38623744    "FLR R0.y, R0.x;\n"
    38633745    "ADD R0.x, R0, -R0.y;\n"
    38643746    "TEX R0, R0, texture[1], 1D;\n"
     3747    "MAD R2.xyz, R0, c[7].w, -R0.w;\n"
     3748    "MAD R4.xyz, R3, R4, c[9].x;\n"
     3749    "MUL R5.xyz, R1.w, R2;\n"
     3750    "MUL R6.xyz, R5, R4;\n"
     3751    "RSQ R2.w, R3.x;\n"
     3752    "RCP R4.x, R2.w;\n"
     3753    "RSQ R2.w, R3.y;\n"
     3754    "RSQ R3.w, R3.z;\n"
     3755    "RCP R4.y, R2.w;\n"
     3756    "RCP R4.z, R3.w;\n"
     3757    "ADD R4.xyz, -R3, R4;\n"
     3758    "MUL R6.xyz, R3, R6;\n"
     3759    "MUL R4.xyz, R5, R4;\n"
     3760    "ADD R3.xyz, -R3, c[7].z;\n"
     3761    "MAD R2.xyz, R2, R3, R0.w;\n"
     3762    "MUL R3.xyz, R0, c[7].w;\n"
     3763    "MAD R5.xyz, R0.w, R1, R6;\n"
     3764    "MAD R4.xyz, R0.w, R1, R4;\n"
     3765    "ADD R6.xyz, R4, -R5;\n"
     3766    "MUL R4.xyz, R1, c[8].y;\n"
     3767    "SGE R4.xyz, R4, R1.w;\n"
     3768    "MAD R4.xyz, R4, R6, R5;\n"
     3769    "MAD R4.xyz, -R1, R2, R4;\n"
     3770    "MUL R2.xyz, R1, R2;\n"
     3771    "SGE R3.xyz, R3, R0.w;\n"
     3772    "MAD R2.xyz, R3, R4, R2;\n"
     3773    "ADD R2.w, -R1, c[7].z;\n"
     3774    "MAD R2.xyz, R0, R2.w, R2;\n"
     3775    "ADD R0.x, R0.w, R1.w;\n"
     3776    "ADD R0.y, -R0.w, c[7].z;\n"
     3777    "MAD result.color.xyz, R1, R0.y, R2;\n"
     3778    "MAD result.color.w, -R0, R1, R0.x;\n"
     3779    "END\n"
     3780    ;
     3781
     3782static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_DIFFERENCE_NOMASK =
     3783    "!!ARBfp1.0\n"
     3784    "PARAM c[8] = { program.local[0..4],\n"
     3785    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3786    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3787    "           { 0.33299461, 0.99999559, 2 } };\n"
     3788    "TEMP R0;\n"
     3789    "TEMP R1;\n"
     3790    "TEMP R2;\n"
     3791    "TEMP R3;\n"
     3792    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3793    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3794    "ADD R0.xyz, R0, c[3];\n"
     3795    "RCP R0.z, R0.z;\n"
     3796    "MUL R0.xy, R0, R0.z;\n"
     3797    "ABS R0.z, R0.x;\n"
     3798    "ABS R0.w, R0.y;\n"
     3799    "ADD R0.w, R0, -R0.z;\n"
     3800    "ADD R1.x, R0.y, c[5].y;\n"
     3801    "ABS R0.w, R0;\n"
     3802    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3803    "ABS R0.w, -R0.y;\n"
     3804    "MAX R1.x, R0.z, R0.w;\n"
     3805    "RCP R1.y, R1.x;\n"
     3806    "MIN R1.x, R0.z, R0.w;\n"
     3807    "MUL R1.x, R1, R1.y;\n"
     3808    "MUL R1.y, R1.x, R1.x;\n"
     3809    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3810    "MAD R1.z, R1, R1.y, -c[6];\n"
     3811    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3812    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3813    "MAD R1.y, R1.z, R1, c[7];\n"
     3814    "MUL R1.x, R1.y, R1;\n"
     3815    "ADD R0.z, -R0, R0.w;\n"
     3816    "ADD R1.y, -R1.x, c[5].w;\n"
     3817    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3818    "ADD R0.w, -R0.z, c[5].z;\n"
     3819    "CMP R0.x, R0, R0.w, R0.z;\n"
     3820    "CMP R0.x, -R0.y, -R0, R0;\n"
     3821    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3822    "ADD R0.x, R0, c[0];\n"
     3823    "MUL R0.x, R0, c[5];\n"
     3824    "FLR R0.y, R0.x;\n"
     3825    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3826    "ADD R0.x, R0, -R0.y;\n"
     3827    "TEX R0, R0, texture[1], 1D;\n"
    38653828    "MUL R2.xyz, R0, R1.w;\n"
    3866     "MUL R3.xyz, R1, R0.w;\n"
     3829    "MUL R3.xyz, R0.w, R1;\n"
    38673830    "ADD R0.xyz, R0, R1;\n"
    38683831    "MIN R2.xyz, R2, R3;\n"
    38693832    "ADD R1.x, R0.w, R1.w;\n"
    3870     "MAD result.color.xyz, -R2, c[6].y, R0;\n"
     3833    "MAD result.color.xyz, -R2, c[7].z, R0;\n"
    38713834    "MAD result.color.w, -R0, R1, R1.x;\n"
    38723835    "END\n"
     
    38753838static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODES_EXCLUSION_NOMASK =
    38763839    "!!ARBfp1.0\n"
    3877     "PARAM c[8] = { program.local[0..2],\n"
    3878     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3879     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3880     "           program.local[5],\n"
    3881     "           { 0.15915494, 2 },\n"
    3882     "           program.local[7] };\n"
    3883     "TEMP R0;\n"
    3884     "TEMP R1;\n"
    3885     "TEMP R2;\n"
    3886     "TEMP R3;\n"
    3887     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3888     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3889     "ADD R0.xyz, R0, c[2];\n"
    3890     "RCP R0.z, R0.z;\n"
    3891     "MUL R0.xy, R0, R0.z;\n"
    3892     "ABS R0.w, R0.x;\n"
    3893     "ABS R0.z, R0.y;\n"
    3894     "ADD R0.z, R0, -R0.w;\n"
    3895     "ADD R0.w, R0.y, c[3].x;\n"
    3896     "ABS R0.z, R0;\n"
    3897     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3898     "ABS R0.z, -R0.y;\n"
    3899     "ADD R0.z, R0, c[3].y;\n"
    3900     "ADD R0.w, R0.x, R0.z;\n"
    3901     "ADD R1.x, R0.z, -R0;\n"
    3902     "RCP R1.y, R0.w;\n"
    3903     "RCP R1.x, R1.x;\n"
    3904     "MUL R0.w, R0, R1.x;\n"
    3905     "ADD R0.z, R0.x, -R0;\n"
    3906     "MUL R0.z, R0, R1.y;\n"
    3907     "CMP R0.z, R0.x, R0.w, R0;\n"
    3908     "MUL R0.w, R0.z, R0.z;\n"
    3909     "MOV R1.x, c[4].y;\n"
    3910     "CMP R0.x, R0, c[4], R1;\n"
    3911     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3912     "MUL R1.xy, fragment.position, c[7];\n"
    3913     "TEX R1, R1, texture[0], 2D;\n"
    3914     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3915     "MAD R0.x, R0.w, R0.z, R0;\n"
    3916     "MAD R0.x, R0, R0.y, c[5];\n"
    3917     "MUL R0.x, R0, c[6];\n"
     3840    "PARAM c[8] = { program.local[0..4],\n"
     3841    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3842    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3843    "           { 0.33299461, 0.99999559, 2, 1 } };\n"
     3844    "TEMP R0;\n"
     3845    "TEMP R1;\n"
     3846    "TEMP R2;\n"
     3847    "TEMP R3;\n"
     3848    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3849    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3850    "ADD R0.xyz, R0, c[3];\n"
     3851    "RCP R0.z, R0.z;\n"
     3852    "MUL R0.xy, R0, R0.z;\n"
     3853    "ABS R0.z, R0.x;\n"
     3854    "ABS R0.w, R0.y;\n"
     3855    "ADD R0.w, R0, -R0.z;\n"
     3856    "ADD R1.x, R0.y, c[5].y;\n"
     3857    "ABS R0.w, R0;\n"
     3858    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3859    "ABS R0.w, -R0.y;\n"
     3860    "MAX R1.x, R0.z, R0.w;\n"
     3861    "RCP R1.y, R1.x;\n"
     3862    "MIN R1.x, R0.z, R0.w;\n"
     3863    "MUL R1.x, R1, R1.y;\n"
     3864    "MUL R1.y, R1.x, R1.x;\n"
     3865    "MAD R1.z, R1.y, c[6].x, c[6].y;\n"
     3866    "MAD R1.z, R1, R1.y, -c[6];\n"
     3867    "MAD R1.z, R1, R1.y, c[6].w;\n"
     3868    "MAD R1.z, R1, R1.y, -c[7].x;\n"
     3869    "MAD R1.y, R1.z, R1, c[7];\n"
     3870    "MUL R1.x, R1.y, R1;\n"
     3871    "ADD R0.z, -R0, R0.w;\n"
     3872    "ADD R1.y, -R1.x, c[5].w;\n"
     3873    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3874    "ADD R0.w, -R0.z, c[5].z;\n"
     3875    "CMP R0.x, R0, R0.w, R0.z;\n"
     3876    "CMP R0.x, -R0.y, -R0, R0;\n"
     3877    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     3878    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     3879    "ADD R0.x, R0, c[0];\n"
     3880    "MUL R0.x, R0, c[5];\n"
    39183881    "FLR R0.y, R0.x;\n"
    39193882    "ADD R0.x, R0, -R0.y;\n"
    39203883    "TEX R0, R0, texture[1], 1D;\n"
    3921     "MUL R2.xyz, R1, R0.w;\n"
     3884    "MUL R2.xyz, R0.w, R1;\n"
    39223885    "MAD R3.xyz, R0, R1.w, R2;\n"
    39233886    "MUL R2.xyz, R0, R1;\n"
    3924     "MAD R2.xyz, -R2, c[6].y, R3;\n"
    3925     "ADD R2.w, -R1, c[4];\n"
     3887    "MAD R2.xyz, -R2, c[7].z, R3;\n"
     3888    "ADD R2.w, -R1, c[7];\n"
    39263889    "MAD R0.xyz, R0, R2.w, R2;\n"
    39273890    "ADD R2.x, R0.w, R1.w;\n"
    3928     "ADD R2.y, -R0.w, c[4].w;\n"
     3891    "ADD R2.y, -R0.w, c[7].w;\n"
    39293892    "MAD result.color.xyz, R1, R2.y, R0;\n"
    39303893    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    39343897static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_MASK =
    39353898    "!!ARBfp1.0\n"
    3936     "PARAM c[10] = { program.local[0..2],\n"
    3937     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3938     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3939     "           program.local[5],\n"
    3940     "           { 0.15915494 },\n"
    3941     "           program.local[7..9] };\n"
    3942     "TEMP R0;\n"
    3943     "TEMP R1;\n"
    3944     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3945     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3946     "ADD R0.xyz, R0, c[2];\n"
    3947     "RCP R0.z, R0.z;\n"
    3948     "MUL R0.xy, R0, R0.z;\n"
    3949     "ABS R0.w, R0.x;\n"
    3950     "ABS R0.z, R0.y;\n"
    3951     "ADD R0.z, R0, -R0.w;\n"
    3952     "ADD R0.w, R0.y, c[3].x;\n"
    3953     "ABS R0.z, R0;\n"
    3954     "CMP R0.y, -R0.z, R0, R0.w;\n"
    3955     "ABS R0.z, -R0.y;\n"
    3956     "ADD R0.z, R0, c[3].y;\n"
    3957     "ADD R0.w, R0.x, R0.z;\n"
    3958     "ADD R1.x, R0.z, -R0;\n"
    3959     "RCP R1.y, R0.w;\n"
    3960     "RCP R1.x, R1.x;\n"
    3961     "MUL R0.w, R0, R1.x;\n"
    3962     "ADD R0.z, R0.x, -R0;\n"
    3963     "MUL R0.z, R0, R1.y;\n"
    3964     "CMP R0.z, R0.x, R0.w, R0;\n"
    3965     "MUL R0.w, R0.z, R0.z;\n"
    3966     "MOV R1.x, c[4].y;\n"
    3967     "CMP R0.x, R0, c[4], R1;\n"
    3968     "MAD R0.w, R0, c[3].z, -c[3];\n"
    3969     "MAD R0.x, R0.w, R0.z, R0;\n"
    3970     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    3971     "MAD R0.z, R0.x, R0.y, c[5].x;\n"
    3972     "MUL R1.x, R0.z, c[6];\n"
     3899    "PARAM c[10] = { program.local[0..6],\n"
     3900    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3901    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3902    "           { 0.33299461, 0.99999559 } };\n"
     3903    "TEMP R0;\n"
     3904    "TEMP R1;\n"
     3905    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3906    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3907    "ADD R0.xyz, R0, c[3];\n"
     3908    "RCP R0.z, R0.z;\n"
     3909    "MUL R0.xy, R0, R0.z;\n"
     3910    "ABS R0.z, R0.x;\n"
     3911    "ABS R0.w, R0.y;\n"
     3912    "ADD R0.w, R0, -R0.z;\n"
     3913    "ADD R1.x, R0.y, c[7].y;\n"
     3914    "ABS R0.w, R0;\n"
     3915    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3916    "ABS R0.w, -R0.y;\n"
     3917    "MAX R1.x, R0.z, R0.w;\n"
     3918    "RCP R1.y, R1.x;\n"
     3919    "MIN R1.x, R0.z, R0.w;\n"
     3920    "MUL R1.x, R1, R1.y;\n"
     3921    "MUL R1.y, R1.x, R1.x;\n"
     3922    "MAD R1.z, R1.y, c[8].x, c[8].y;\n"
     3923    "MAD R1.z, R1, R1.y, -c[8];\n"
     3924    "MAD R1.z, R1, R1.y, c[8].w;\n"
     3925    "MAD R1.z, R1, R1.y, -c[9].x;\n"
     3926    "MAD R1.y, R1.z, R1, c[9];\n"
     3927    "MUL R1.x, R1.y, R1;\n"
     3928    "ADD R1.y, -R1.x, c[7].w;\n"
     3929    "ADD R0.z, -R0, R0.w;\n"
     3930    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3931    "ADD R0.w, -R0.z, c[7].z;\n"
     3932    "CMP R0.x, R0, R0.w, R0.z;\n"
     3933    "CMP R0.x, -R0.y, -R0, R0;\n"
     3934    "ADD R0.x, R0, c[0];\n"
     3935    "MUL R1.x, R0, c[7];\n"
    39733936    "FLR R1.y, R1.x;\n"
    3974     "ADD R0.xy, fragment.position, c[7];\n"
    3975     "MUL R0.xy, R0, c[8];\n"
     3937    "ADD R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     3938    "MUL R0.xy, R0.zwzw, c[4];\n"
    39763939    "TEX R0, R0, texture[0], 2D;\n"
    39773940    "ADD R1.x, R1, -R1.y;\n"
    3978     "DP4 R1.y, R0, c[9];\n"
     3941    "DP4 R1.y, R0, c[6];\n"
    39793942    "TEX R0, R1, texture[1], 1D;\n"
    39803943    "MUL result.color, R0, R1.y;\n"
     
    39843947static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_CONICAL_COMPOSITION_MODE_BLEND_MODE_NOMASK =
    39853948    "!!ARBfp1.0\n"
    3986     "PARAM c[7] = { program.local[0..2],\n"
    3987     "           { 0.0020000001, 9.9999997e-10, 0.1963, 0.9817 },\n"
    3988     "           { 2.3561945, 0.78539819, -1, 1 },\n"
    3989     "           program.local[5],\n"
    3990     "           { 0.15915494 } };\n"
    3991     "TEMP R0;\n"
    3992     "TEMP R1;\n"
    3993     "MUL R0.xyz, fragment.position.y, c[1];\n"
    3994     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    3995     "ADD R0.xyz, R0, c[2];\n"
    3996     "RCP R0.z, R0.z;\n"
    3997     "MUL R0.xy, R0, R0.z;\n"
    3998     "ABS R0.w, R0.x;\n"
    3999     "ABS R0.z, R0.y;\n"
    4000     "ADD R0.z, R0, -R0.w;\n"
    4001     "ADD R0.w, R0.y, c[3].x;\n"
    4002     "ABS R0.z, R0;\n"
    4003     "CMP R0.y, -R0.z, R0, R0.w;\n"
    4004     "ABS R0.z, -R0.y;\n"
    4005     "ADD R0.z, R0, c[3].y;\n"
    4006     "ADD R0.w, R0.x, R0.z;\n"
    4007     "ADD R1.x, R0.z, -R0;\n"
    4008     "RCP R1.x, R1.x;\n"
    4009     "RCP R1.y, R0.w;\n"
    4010     "MUL R0.w, R0, R1.x;\n"
    4011     "ADD R0.z, R0.x, -R0;\n"
    4012     "MUL R0.z, R0, R1.y;\n"
    4013     "CMP R0.z, R0.x, R0.w, R0;\n"
    4014     "MUL R0.w, R0.z, R0.z;\n"
    4015     "MOV R1.x, c[4].y;\n"
    4016     "CMP R0.y, -R0, c[4].z, c[4].w;\n"
    4017     "MAD R0.w, R0, c[3].z, -c[3];\n"
    4018     "CMP R0.x, R0, c[4], R1;\n"
    4019     "MAD R0.x, R0.w, R0.z, R0;\n"
    4020     "MAD R0.x, R0, R0.y, c[5];\n"
    4021     "MUL R0.x, R0, c[6];\n"
     3949    "PARAM c[7] = { program.local[0..3],\n"
     3950    "           { 0.15915494, 0.0020000001, 3.141593, 1.570796 },\n"
     3951    "           { -0.01348047, 0.05747731, 0.1212391, 0.1956359 },\n"
     3952    "           { 0.33299461, 0.99999559 } };\n"
     3953    "TEMP R0;\n"
     3954    "TEMP R1;\n"
     3955    "MUL R0.xyz, fragment.position.y, c[2];\n"
     3956    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     3957    "ADD R0.xyz, R0, c[3];\n"
     3958    "RCP R0.z, R0.z;\n"
     3959    "MUL R0.xy, R0, R0.z;\n"
     3960    "ABS R0.z, R0.x;\n"
     3961    "ABS R0.w, R0.y;\n"
     3962    "ADD R0.w, R0, -R0.z;\n"
     3963    "ADD R1.x, R0.y, c[4].y;\n"
     3964    "ABS R0.w, R0;\n"
     3965    "CMP R0.y, -R0.w, R0, R1.x;\n"
     3966    "ABS R0.w, -R0.y;\n"
     3967    "MAX R1.x, R0.z, R0.w;\n"
     3968    "RCP R1.y, R1.x;\n"
     3969    "MIN R1.x, R0.z, R0.w;\n"
     3970    "MUL R1.x, R1, R1.y;\n"
     3971    "MUL R1.y, R1.x, R1.x;\n"
     3972    "MAD R1.z, R1.y, c[5].x, c[5].y;\n"
     3973    "MAD R1.z, R1, R1.y, -c[5];\n"
     3974    "MAD R1.z, R1, R1.y, c[5].w;\n"
     3975    "MAD R1.z, R1, R1.y, -c[6].x;\n"
     3976    "MAD R1.y, R1.z, R1, c[6];\n"
     3977    "MUL R1.x, R1.y, R1;\n"
     3978    "ADD R0.z, -R0, R0.w;\n"
     3979    "ADD R1.y, -R1.x, c[4].w;\n"
     3980    "CMP R0.z, -R0, R1.y, R1.x;\n"
     3981    "ADD R0.w, -R0.z, c[4].z;\n"
     3982    "CMP R0.x, R0, R0.w, R0.z;\n"
     3983    "CMP R0.x, -R0.y, -R0, R0;\n"
     3984    "ADD R0.x, R0, c[0];\n"
     3985    "MUL R0.x, R0, c[4];\n"
    40223986    "FLR R0.y, R0.x;\n"
    40233987    "ADD R0.x, R0, -R0.y;\n"
     
    40283992static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    40293993    "!!ARBfp1.0\n"
    4030     "PARAM c[11] = { program.local[0..7],\n"
    4031     "           { 1 },\n"
    4032     "           program.local[9..10] };\n"
    4033     "TEMP R0;\n"
    4034     "TEMP R1;\n"
    4035     "TEMP R2;\n"
    4036     "TEMP R3;\n"
    4037     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4038     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4039     "ADD R0.xyz, R0, c[5];\n"
    4040     "RCP R0.z, R0.z;\n"
    4041     "MUL R0.xy, R0, R0.z;\n"
    4042     "MUL R0.xy, R0, c[6];\n"
    4043     "ADD R0.x, R0, R0.y;\n"
    4044     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    4045     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4046     "MUL R0.x, R0, c[6].z;\n"
    4047     "TEX R0, R0, texture[2], 1D;\n"
    4048     "MUL R2.xyz, R1, c[10].y;\n"
    4049     "MUL R3.xyz, R2, R0.w;\n"
    4050     "MUL R2.xyz, R0, c[10].x;\n"
    4051     "MAD R2.xyz, R2, R1.w, R3;\n"
    4052     "ADD R3.xy, fragment.position, c[0];\n"
    4053     "MUL R0.xyz, R0, c[9].y;\n"
    4054     "ADD R2.w, -R1, c[8].x;\n"
    4055     "MAD R2.xyz, R0, R2.w, R2;\n"
    4056     "MUL R0.xyz, R1, c[9].z;\n"
    4057     "ADD R2.w, -R0, c[8].x;\n"
    4058     "MAD R2.xyz, R0, R2.w, R2;\n"
    4059     "ADD R0.y, -R1.w, c[8].x;\n"
    4060     "MUL R0.z, R1.w, R2.w;\n"
    4061     "MUL R0.x, R0.w, R1.w;\n"
    4062     "MUL R0.y, R0.w, R0;\n"
    4063     "DP3 R2.w, R0, c[9];\n"
    4064     "MUL R3.xy, R3, c[1];\n"
    4065     "TEX R0, R3, texture[1], 2D;\n"
    4066     "ADD R2, R2, -R1;\n"
    4067     "DP4 R0.x, R0, c[2];\n"
    4068     "MAD result.color, R0.x, R2, R1;\n"
     3994    "PARAM c[11] = { program.local[0..9],\n"
     3995    "           { 1 } };\n"
     3996    "TEMP R0;\n"
     3997    "TEMP R1;\n"
     3998    "TEMP R2;\n"
     3999    "TEMP R3;\n"
     4000    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4001    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4002    "ADD R0.xyz, R0, c[3];\n"
     4003    "RCP R0.z, R0.z;\n"
     4004    "MUL R0.xy, R0, R0.z;\n"
     4005    "MUL R0.zw, R0.xyxy, c[0].xyxy;\n"
     4006    "ADD R1.x, R0.z, R0.w;\n"
     4007    "MUL R0.xy, fragment.position, c[7];\n"
     4008    "TEX R0, R0, texture[0], 2D;\n"
     4009    "MUL R1.x, R1, c[0].z;\n"
     4010    "TEX R1, R1, texture[2], 1D;\n"
     4011    "MUL R2.xyz, R0, c[4].y;\n"
     4012    "MUL R3.xyz, R1.w, R2;\n"
     4013    "MUL R2.xyz, R1, c[4].x;\n"
     4014    "MAD R2.xyz, R0.w, R2, R3;\n"
     4015    "ADD R3.xy, fragment.position, c[8];\n"
     4016    "ADD R2.w, -R0, c[10].x;\n"
     4017    "MUL R1.xyz, R1, c[5].y;\n"
     4018    "MAD R2.xyz, R2.w, R1, R2;\n"
     4019    "MUL R1.xyz, R0, c[5].z;\n"
     4020    "ADD R3.z, -R1.w, c[10].x;\n"
     4021    "MAD R2.xyz, R3.z, R1, R2;\n"
     4022    "MUL R1.y, R1.w, R2.w;\n"
     4023    "MUL R1.x, R1.w, R0.w;\n"
     4024    "MUL R1.z, R0.w, R3;\n"
     4025    "DP3 R2.w, R1, c[5];\n"
     4026    "MUL R3.xy, R3, c[6];\n"
     4027    "TEX R1, R3, texture[1], 2D;\n"
     4028    "ADD R2, R2, -R0;\n"
     4029    "DP4 R1.x, R1, c[9];\n"
     4030    "MAD result.color, R1.x, R2, R0;\n"
    40694031    "END\n"
    40704032    ;
     
    40774039    "TEMP R1;\n"
    40784040    "TEMP R2;\n"
    4079     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4080     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4081     "ADD R0.xyz, R0, c[5];\n"
    4082     "RCP R0.z, R0.z;\n"
    4083     "MUL R0.xy, R0, R0.z;\n"
    4084     "MUL R0.xy, R0, c[6];\n"
     4041    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4042    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4043    "ADD R0.xyz, R0, c[3];\n"
     4044    "RCP R0.z, R0.z;\n"
     4045    "MUL R0.xy, R0, R0.z;\n"
     4046    "MUL R0.zw, R0.xyxy, c[0].xyxy;\n"
     4047    "ADD R1.x, R0.z, R0.w;\n"
     4048    "MUL R0.xy, fragment.position, c[5];\n"
     4049    "TEX R0, R0, texture[0], 2D;\n"
     4050    "MUL R1.x, R1, c[0].z;\n"
     4051    "TEX R1, R1, texture[2], 1D;\n"
     4052    "ADD R2.x, -R0.w, c[8];\n"
     4053    "MUL R2.xyz, R1, R2.x;\n"
     4054    "MAD R1.xyz, R1, R0, R2;\n"
     4055    "ADD R2.x, -R1.w, c[8];\n"
     4056    "MAD R2.xyz, R0, R2.x, R1;\n"
     4057    "ADD R1.z, R1.w, R0.w;\n"
     4058    "MAD R2.w, -R1, R0, R1.z;\n"
     4059    "ADD R1.xy, fragment.position, c[6];\n"
     4060    "MUL R1.xy, R1, c[4];\n"
     4061    "TEX R1, R1, texture[1], 2D;\n"
     4062    "ADD R2, R2, -R0;\n"
     4063    "DP4 R1.x, R1, c[7];\n"
     4064    "MAD result.color, R1.x, R2, R0;\n"
     4065    "END\n"
     4066    ;
     4067
     4068static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN =
     4069    "!!ARBfp1.0\n"
     4070    "PARAM c[8] = { program.local[0..7] };\n"
     4071    "TEMP R0;\n"
     4072    "TEMP R1;\n"
     4073    "TEMP R2;\n"
     4074    "TEMP R3;\n"
     4075    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4076    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4077    "ADD R0.xyz, R0, c[3];\n"
     4078    "RCP R0.z, R0.z;\n"
     4079    "MUL R0.xy, R0, R0.z;\n"
     4080    "MUL R0.xy, R0, c[0];\n"
    40854081    "ADD R0.x, R0, R0.y;\n"
    4086     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    4087     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4088     "MUL R0.x, R0, c[6].z;\n"
    4089     "TEX R0, R0, texture[2], 1D;\n"
    4090     "ADD R2.x, -R1.w, c[8];\n"
    4091     "MUL R2.xyz, R0, R2.x;\n"
    4092     "MAD R0.xyz, R0, R1, R2;\n"
    4093     "ADD R2.x, -R0.w, c[8];\n"
    4094     "MAD R2.xyz, R1, R2.x, R0;\n"
    4095     "ADD R0.z, R0.w, R1.w;\n"
    4096     "MAD R2.w, -R0, R1, R0.z;\n"
    4097     "ADD R0.xy, fragment.position, c[0];\n"
    4098     "MUL R0.xy, R0, c[1];\n"
    4099     "TEX R0, R0, texture[1], 2D;\n"
    4100     "ADD R2, R2, -R1;\n"
    4101     "DP4 R0.x, R0, c[2];\n"
    4102     "MAD result.color, R0.x, R2, R1;\n"
    4103     "END\n"
    4104     ;
    4105 
    4106 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SCREEN =
    4107     "!!ARBfp1.0\n"
    4108     "PARAM c[8] = { program.local[0..7] };\n"
    4109     "TEMP R0;\n"
    4110     "TEMP R1;\n"
    4111     "TEMP R2;\n"
    4112     "TEMP R3;\n"
    4113     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4114     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4115     "ADD R0.xyz, R0, c[5];\n"
    4116     "RCP R0.z, R0.z;\n"
    4117     "MUL R0.xy, R0, R0.z;\n"
    4118     "MUL R0.xy, R0, c[6];\n"
    4119     "ADD R0.x, R0, R0.y;\n"
    4120     "MUL R0.x, R0, c[6].z;\n"
    4121     "MUL R1.xy, fragment.position, c[7];\n"
    4122     "ADD R3.xy, fragment.position, c[0];\n"
    4123     "TEX R1, R1, texture[0], 2D;\n"
    4124     "TEX R0, R0, texture[2], 1D;\n"
    4125     "ADD R2, R0, R1;\n"
    4126     "MAD R2, -R0, R1, R2;\n"
    4127     "MUL R3.xy, R3, c[1];\n"
    4128     "TEX R0, R3, texture[1], 2D;\n"
    4129     "ADD R2, R2, -R1;\n"
    4130     "DP4 R0.x, R0, c[2];\n"
    4131     "MAD result.color, R0.x, R2, R1;\n"
     4082    "MUL R0.z, R0.x, c[0];\n"
     4083    "ADD R3.xy, fragment.position, c[6];\n"
     4084    "TEX R1, R0.z, texture[2], 1D;\n"
     4085    "MUL R0.xy, fragment.position, c[5];\n"
     4086    "TEX R0, R0, texture[0], 2D;\n"
     4087    "ADD R2, R1, R0;\n"
     4088    "MAD R2, -R1, R0, R2;\n"
     4089    "MUL R3.xy, R3, c[4];\n"
     4090    "TEX R1, R3, texture[1], 2D;\n"
     4091    "ADD R2, R2, -R0;\n"
     4092    "DP4 R1.x, R1, c[7];\n"
     4093    "MAD result.color, R1.x, R2, R0;\n"
    41324094    "END\n"
    41334095    ;
     
    41424104    "TEMP R3;\n"
    41434105    "TEMP R4;\n"
    4144     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4145     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4146     "ADD R0.xyz, R0, c[5];\n"
    4147     "RCP R0.z, R0.z;\n"
    4148     "MUL R0.xy, R0, R0.z;\n"
    4149     "MUL R0.xy, R0, c[6];\n"
     4106    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4107    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4108    "ADD R0.xyz, R0, c[3];\n"
     4109    "RCP R0.z, R0.z;\n"
     4110    "MUL R0.xy, R0, R0.z;\n"
     4111    "MUL R0.xy, R0, c[0];\n"
    41504112    "ADD R0.x, R0, R0.y;\n"
    4151     "MUL R0.x, R0, c[6].z;\n"
     4113    "MUL R0.x, R0, c[0].z;\n"
    41524114    "TEX R0, R0, texture[2], 1D;\n"
    4153     "MUL R1.xy, fragment.position, c[7];\n"
     4115    "MUL R1.xy, fragment.position, c[5];\n"
    41544116    "TEX R1, R1, texture[0], 2D;\n"
    41554117    "ADD R2.w, -R1, c[8].y;\n"
     
    41724134    "ADD R0.z, R0.w, R1.w;\n"
    41734135    "MAD R2.w, -R0, R1, R0.z;\n"
    4174     "ADD R0.xy, fragment.position, c[0];\n"
    4175     "MUL R0.xy, R0, c[1];\n"
     4136    "ADD R0.xy, fragment.position, c[6];\n"
     4137    "MUL R0.xy, R0, c[4];\n"
    41764138    "TEX R0, R0, texture[1], 2D;\n"
    41774139    "ADD R2, R2, -R1;\n"
    4178     "DP4 R0.x, R0, c[2];\n"
     4140    "DP4 R0.x, R0, c[7];\n"
    41794141    "MAD result.color, R0.x, R2, R1;\n"
    41804142    "END\n"
     
    41894151    "TEMP R2;\n"
    41904152    "TEMP R3;\n"
    4191     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4192     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4193     "ADD R0.xyz, R0, c[5];\n"
    4194     "RCP R0.z, R0.z;\n"
    4195     "MUL R0.xy, R0, R0.z;\n"
    4196     "MUL R0.xy, R0, c[6];\n"
    4197     "ADD R0.x, R0, R0.y;\n"
    4198     "MUL R0.x, R0, c[6].z;\n"
    4199     "MUL R1.xy, fragment.position, c[7];\n"
    4200     "TEX R1, R1, texture[0], 2D;\n"
    4201     "TEX R0, R0, texture[2], 1D;\n"
    4202     "MUL R3.xyz, R1, R0.w;\n"
    4203     "MUL R2.xyz, R0, R1.w;\n"
     4153    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4154    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4155    "ADD R0.xyz, R0, c[3];\n"
     4156    "RCP R0.z, R0.z;\n"
     4157    "MUL R0.xy, R0, R0.z;\n"
     4158    "MUL R0.xy, R0, c[0];\n"
     4159    "ADD R0.z, R0.x, R0.y;\n"
     4160    "MUL R1.x, R0.z, c[0].z;\n"
     4161    "MUL R0.xy, fragment.position, c[5];\n"
     4162    "TEX R0, R0, texture[0], 2D;\n"
     4163    "TEX R1, R1, texture[2], 1D;\n"
     4164    "MUL R3.xyz, R1.w, R0;\n"
     4165    "MUL R2.xyz, R1, R0.w;\n"
    42044166    "MIN R2.xyz, R2, R3;\n"
    4205     "ADD R2.w, -R1, c[8].x;\n"
    4206     "MAD R0.xyz, R0, R2.w, R2;\n"
    4207     "ADD R2.x, -R0.w, c[8];\n"
    4208     "MAD R2.xyz, R1, R2.x, R0;\n"
    4209     "ADD R0.z, R0.w, R1.w;\n"
    4210     "MAD R2.w, -R0, R1, R0.z;\n"
    4211     "ADD R0.xy, fragment.position, c[0];\n"
    4212     "MUL R0.xy, R0, c[1];\n"
    4213     "TEX R0, R0, texture[1], 2D;\n"
    4214     "ADD R2, R2, -R1;\n"
    4215     "DP4 R0.x, R0, c[2];\n"
    4216     "MAD result.color, R0.x, R2, R1;\n"
     4167    "ADD R2.w, -R0, c[8].x;\n"
     4168    "MAD R1.xyz, R1, R2.w, R2;\n"
     4169    "ADD R2.x, -R1.w, c[8];\n"
     4170    "MAD R2.xyz, R0, R2.x, R1;\n"
     4171    "ADD R1.z, R1.w, R0.w;\n"
     4172    "MAD R2.w, -R1, R0, R1.z;\n"
     4173    "ADD R1.xy, fragment.position, c[6];\n"
     4174    "MUL R1.xy, R1, c[4];\n"
     4175    "TEX R1, R1, texture[1], 2D;\n"
     4176    "ADD R2, R2, -R0;\n"
     4177    "DP4 R1.x, R1, c[7];\n"
     4178    "MAD result.color, R1.x, R2, R0;\n"
    42174179    "END\n"
    42184180    ;
     
    42264188    "TEMP R2;\n"
    42274189    "TEMP R3;\n"
    4228     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4229     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4230     "ADD R0.xyz, R0, c[5];\n"
    4231     "RCP R0.z, R0.z;\n"
    4232     "MUL R0.xy, R0, R0.z;\n"
    4233     "MUL R0.xy, R0, c[6];\n"
     4190    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4191    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4192    "ADD R0.xyz, R0, c[3];\n"
     4193    "RCP R0.z, R0.z;\n"
     4194    "MUL R0.xy, R0, R0.z;\n"
     4195    "MUL R0.xy, R0, c[0];\n"
     4196    "ADD R0.z, R0.x, R0.y;\n"
     4197    "MUL R1.x, R0.z, c[0].z;\n"
     4198    "MUL R0.xy, fragment.position, c[5];\n"
     4199    "TEX R0, R0, texture[0], 2D;\n"
     4200    "TEX R1, R1, texture[2], 1D;\n"
     4201    "MUL R3.xyz, R1.w, R0;\n"
     4202    "MUL R2.xyz, R1, R0.w;\n"
     4203    "MAX R2.xyz, R2, R3;\n"
     4204    "ADD R2.w, -R0, c[8].x;\n"
     4205    "MAD R1.xyz, R1, R2.w, R2;\n"
     4206    "ADD R2.x, -R1.w, c[8];\n"
     4207    "MAD R2.xyz, R0, R2.x, R1;\n"
     4208    "ADD R1.z, R1.w, R0.w;\n"
     4209    "MAD R2.w, -R1, R0, R1.z;\n"
     4210    "ADD R1.xy, fragment.position, c[6];\n"
     4211    "MUL R1.xy, R1, c[4];\n"
     4212    "TEX R1, R1, texture[1], 2D;\n"
     4213    "ADD R2, R2, -R0;\n"
     4214    "DP4 R1.x, R1, c[7];\n"
     4215    "MAD result.color, R1.x, R2, R0;\n"
     4216    "END\n"
     4217    ;
     4218
     4219static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE =
     4220    "!!ARBfp1.0\n"
     4221    "PARAM c[9] = { program.local[0..7],\n"
     4222    "           { 1, 1e-006 } };\n"
     4223    "TEMP R0;\n"
     4224    "TEMP R1;\n"
     4225    "TEMP R2;\n"
     4226    "TEMP R3;\n"
     4227    "TEMP R4;\n"
     4228    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4229    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4230    "ADD R0.xyz, R0, c[3];\n"
     4231    "RCP R0.z, R0.z;\n"
     4232    "MUL R0.xy, R0, R0.z;\n"
     4233    "MUL R0.xy, R0, c[0];\n"
    42344234    "ADD R0.x, R0, R0.y;\n"
    4235     "MUL R0.x, R0, c[6].z;\n"
    4236     "MUL R1.xy, fragment.position, c[7];\n"
    4237     "TEX R1, R1, texture[0], 2D;\n"
    4238     "TEX R0, R0, texture[2], 1D;\n"
    4239     "MUL R3.xyz, R1, R0.w;\n"
    4240     "MUL R2.xyz, R0, R1.w;\n"
    4241     "MAX R2.xyz, R2, R3;\n"
    4242     "ADD R2.w, -R1, c[8].x;\n"
    4243     "MAD R0.xyz, R0, R2.w, R2;\n"
    4244     "ADD R2.x, -R0.w, c[8];\n"
    4245     "MAD R2.xyz, R1, R2.x, R0;\n"
    4246     "ADD R0.z, R0.w, R1.w;\n"
    4247     "MAD R2.w, -R0, R1, R0.z;\n"
    4248     "ADD R0.xy, fragment.position, c[0];\n"
    4249     "MUL R0.xy, R0, c[1];\n"
    4250     "TEX R0, R0, texture[1], 2D;\n"
    4251     "ADD R2, R2, -R1;\n"
    4252     "DP4 R0.x, R0, c[2];\n"
    4253     "MAD result.color, R0.x, R2, R1;\n"
    4254     "END\n"
    4255     ;
    4256 
    4257 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_COLORDODGE =
    4258     "!!ARBfp1.0\n"
    4259     "PARAM c[9] = { program.local[0..7],\n"
    4260     "           { 1, 1e-06 } };\n"
    4261     "TEMP R0;\n"
    4262     "TEMP R1;\n"
    4263     "TEMP R2;\n"
    4264     "TEMP R3;\n"
    4265     "TEMP R4;\n"
    4266     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4267     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4268     "ADD R0.xyz, R0, c[5];\n"
    4269     "RCP R0.z, R0.z;\n"
    4270     "MUL R0.xy, R0, R0.z;\n"
    4271     "MUL R0.xy, R0, c[6];\n"
    4272     "ADD R0.x, R0, R0.y;\n"
    4273     "MUL R0.x, R0, c[6].z;\n"
     4235    "MUL R0.x, R0, c[0].z;\n"
    42744236    "TEX R0, R0, texture[2], 1D;\n"
    42754237    "MAX R1.x, R0.w, c[8].y;\n"
     
    42774239    "MAD R2.xyz, -R0, R1.x, c[8].x;\n"
    42784240    "MAX R2.xyz, R2, c[8].y;\n"
    4279     "MUL R1.xy, fragment.position, c[7];\n"
     4241    "MUL R1.xy, fragment.position, c[5];\n"
    42804242    "TEX R1, R1, texture[0], 2D;\n"
    42814243    "ADD R2.w, -R0, c[8].x;\n"
     
    42834245    "ADD R2.w, -R1, c[8].x;\n"
    42844246    "MAD R4.xyz, R0, R2.w, R3;\n"
    4285     "MUL R3.xyz, R1, R0.w;\n"
     4247    "MUL R3.xyz, R0.w, R1;\n"
    42864248    "MUL R2.w, R0, R1;\n"
    42874249    "MAD R0.xyz, R0, R1.w, R3;\n"
     
    42964258    "ADD R0.z, R0.w, R1.w;\n"
    42974259    "MAD R2.w, -R0, R1, R0.z;\n"
    4298     "ADD R0.xy, fragment.position, c[0];\n"
    4299     "MUL R0.xy, R0, c[1];\n"
     4260    "ADD R0.xy, fragment.position, c[6];\n"
     4261    "MUL R0.xy, R0, c[4];\n"
    43004262    "TEX R0, R0, texture[1], 2D;\n"
    43014263    "ADD R2, R2, -R1;\n"
    4302     "DP4 R0.x, R0, c[2];\n"
     4264    "DP4 R0.x, R0, c[7];\n"
    43034265    "MAD result.color, R0.x, R2, R1;\n"
    43044266    "END\n"
     
    43084270    "!!ARBfp1.0\n"
    43094271    "PARAM c[9] = { program.local[0..7],\n"
    4310     "           { 1, 9.9999997e-06 } };\n"
     4272    "           { 1, 9.9999997e-006 } };\n"
    43114273    "TEMP R0;\n"
    43124274    "TEMP R1;\n"
     
    43154277    "TEMP R4;\n"
    43164278    "TEMP R5;\n"
    4317     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4318     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4319     "ADD R0.xyz, R0, c[5];\n"
    4320     "RCP R0.z, R0.z;\n"
    4321     "MUL R0.xy, R0, R0.z;\n"
    4322     "MUL R0.xy, R0, c[6];\n"
     4279    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4280    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4281    "ADD R0.xyz, R0, c[3];\n"
     4282    "RCP R0.z, R0.z;\n"
     4283    "MUL R0.xy, R0, R0.z;\n"
     4284    "MUL R0.xy, R0, c[0];\n"
    43234285    "ADD R0.x, R0, R0.y;\n"
    4324     "MUL R0.x, R0, c[6].z;\n"
     4286    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     4287    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4288    "MUL R0.x, R0, c[0].z;\n"
    43254289    "TEX R0, R0, texture[2], 1D;\n"
    4326     "MUL R1.xy, fragment.position, c[7];\n"
    4327     "TEX R1, R1, texture[0], 2D;\n"
    4328     "MUL R2.xyz, R1, R0.w;\n"
     4290    "MUL R2.xyz, R0.w, R1;\n"
    43294291    "MAD R3.xyz, R0, R1.w, R2;\n"
    43304292    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
     
    43414303    "MAD R0.xyz, R0, R2.w, R4;\n"
    43424304    "MUL R2.w, R0, R1;\n"
    4343     "ADD R3.w, -R0, c[8].x;\n"
    43444305    "MAD R2.xyz, R1, R3.w, R2;\n"
    43454306    "ADD R2.xyz, R2, -R0;\n"
     
    43484309    "ADD R0.z, R0.w, R1.w;\n"
    43494310    "MAD R2.w, -R0, R1, R0.z;\n"
    4350     "ADD R0.xy, fragment.position, c[0];\n"
    4351     "MUL R0.xy, R0, c[1];\n"
     4311    "ADD R0.xy, fragment.position, c[6];\n"
     4312    "MUL R0.xy, R0, c[4];\n"
    43524313    "TEX R0, R0, texture[1], 2D;\n"
    43534314    "ADD R2, R2, -R1;\n"
    4354     "DP4 R0.x, R0, c[2];\n"
     4315    "DP4 R0.x, R0, c[7];\n"
    43554316    "MAD result.color, R0.x, R2, R1;\n"
    43564317    "END\n"
     
    43664327    "TEMP R3;\n"
    43674328    "TEMP R4;\n"
    4368     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4369     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4370     "ADD R0.xyz, R0, c[5];\n"
    4371     "RCP R0.z, R0.z;\n"
    4372     "MUL R0.xy, R0, R0.z;\n"
    4373     "MUL R0.xy, R0, c[6];\n"
     4329    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4330    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4331    "ADD R0.xyz, R0, c[3];\n"
     4332    "RCP R0.z, R0.z;\n"
     4333    "MUL R0.xy, R0, R0.z;\n"
     4334    "MUL R0.xy, R0, c[0];\n"
    43744335    "ADD R0.x, R0, R0.y;\n"
    4375     "MUL R0.x, R0, c[6].z;\n"
     4336    "MUL R0.x, R0, c[0].z;\n"
    43764337    "TEX R0, R0, texture[2], 1D;\n"
    4377     "MUL R1.xy, fragment.position, c[7];\n"
     4338    "MUL R1.xy, fragment.position, c[5];\n"
    43784339    "TEX R1, R1, texture[0], 2D;\n"
    43794340    "ADD R2.w, -R1, c[8].y;\n"
     
    43964357    "ADD R0.z, R0.w, R1.w;\n"
    43974358    "MAD R2.w, -R0, R1, R0.z;\n"
    4398     "ADD R0.xy, fragment.position, c[0];\n"
    4399     "MUL R0.xy, R0, c[1];\n"
     4359    "ADD R0.xy, fragment.position, c[6];\n"
     4360    "MUL R0.xy, R0, c[4];\n"
    44004361    "TEX R0, R0, texture[1], 2D;\n"
    44014362    "ADD R2, R2, -R1;\n"
    4402     "DP4 R0.x, R0, c[2];\n"
     4363    "DP4 R0.x, R0, c[7];\n"
    44034364    "MAD result.color, R0.x, R2, R1;\n"
    44044365    "END\n"
     
    44084369    "!!ARBfp1.0\n"
    44094370    "PARAM c[10] = { program.local[0..7],\n"
    4410     "           { 1, 9.9999997e-06, 2, 8 },\n"
    4411     "           { 3 } };\n"
     4371    "           { 1, 2, 9.9999997e-006, 4 },\n"
     4372    "           { 16, 12, 3 } };\n"
    44124373    "TEMP R0;\n"
    44134374    "TEMP R1;\n"
     
    44174378    "TEMP R5;\n"
    44184379    "TEMP R6;\n"
    4419     "MUL R2.xyz, fragment.position.y, c[4];\n"
    4420     "MAD R3.xyz, fragment.position.x, c[3], R2;\n"
    4421     "MUL R0.xy, fragment.position, c[7];\n"
    4422     "TEX R1, R0, texture[0], 2D;\n"
    4423     "MAX R0.x, R1.w, c[8].y;\n"
    4424     "RCP R2.w, R0.x;\n"
    4425     "MUL R0.xyz, R1, R2.w;\n"
    4426     "RSQ R0.w, R0.x;\n"
    4427     "RSQ R2.y, R0.y;\n"
    4428     "ADD R3.xyz, R3, c[5];\n"
    4429     "RCP R2.x, R0.w;\n"
    4430     "RCP R0.w, R3.z;\n"
    4431     "MUL R3.xy, R3, R0.w;\n"
    4432     "RSQ R0.w, R0.z;\n"
    4433     "RCP R2.z, R0.w;\n"
    4434     "RCP R2.y, R2.y;\n"
    4435     "MAD R6.xyz, R2, R1.w, -R1;\n"
    4436     "MUL R2.xyz, -R0, c[8].w;\n"
    4437     "ADD R5.xyz, R2, c[9].x;\n"
    4438     "MAD R2.xyz, -R1, R2.w, c[8].x;\n"
    4439     "MUL R3.xy, R3, c[6];\n"
    4440     "ADD R0.w, R3.x, R3.y;\n"
    4441     "MUL R0.w, R0, c[6].z;\n"
    4442     "TEX R0, R0.w, texture[2], 1D;\n"
    4443     "MAD R3.xyz, R0, c[8].z, -R0.w;\n"
    4444     "MUL R4.xyz, R2, R3;\n"
    4445     "MAD R4.xyz, -R4, R5, R0.w;\n"
    4446     "MUL R5.xyz, R6, R3;\n"
    4447     "MAD R2.xyz, -R2, R3, R0.w;\n"
    4448     "MAD R6.xyz, R1, R0.w, R5;\n"
    4449     "MUL R4.xyz, R1, R4;\n"
    4450     "MUL R5.xyz, R1, c[8].w;\n"
    4451     "ADD R6.xyz, R6, -R4;\n"
    4452     "SGE R5.xyz, R5, R1.w;\n"
    4453     "MUL R5.xyz, R5, R6;\n"
    4454     "ADD R3.xyz, R4, R5;\n"
     4380    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4381    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4382    "ADD R0.xyz, R0, c[3];\n"
     4383    "RCP R0.z, R0.z;\n"
     4384    "MUL R0.xy, R0, R0.z;\n"
     4385    "MUL R0.xy, R0, c[0];\n"
     4386    "ADD R0.x, R0, R0.y;\n"
     4387    "MUL R1.xy, fragment.position, c[5];\n"
     4388    "TEX R1, R1, texture[0], 2D;\n"
     4389    "MAX R0.z, R1.w, c[8];\n"
     4390    "RCP R0.z, R0.z;\n"
     4391    "MUL R3.xyz, R1, R0.z;\n"
     4392    "MAD R2.xyz, R3, c[9].x, -c[9].y;\n"
     4393    "MUL R0.x, R0, c[0].z;\n"
     4394    "TEX R0, R0, texture[2], 1D;\n"
     4395    "MAD R4.xyz, R3, R2, c[9].z;\n"
     4396    "MAD R2.xyz, R0, c[8].y, -R0.w;\n"
     4397    "MUL R5.xyz, R1.w, R2;\n"
     4398    "MUL R6.xyz, R5, R4;\n"
     4399    "RSQ R2.w, R3.x;\n"
     4400    "RCP R4.x, R2.w;\n"
     4401    "RSQ R2.w, R3.y;\n"
     4402    "RSQ R3.w, R3.z;\n"
     4403    "RCP R4.y, R2.w;\n"
     4404    "RCP R4.z, R3.w;\n"
     4405    "ADD R4.xyz, -R3, R4;\n"
     4406    "MUL R6.xyz, R3, R6;\n"
     4407    "MUL R4.xyz, R5, R4;\n"
     4408    "ADD R3.xyz, -R3, c[8].x;\n"
     4409    "MAD R2.xyz, R2, R3, R0.w;\n"
     4410    "MUL R3.xyz, R0, c[8].y;\n"
     4411    "MAD R5.xyz, R0.w, R1, R6;\n"
     4412    "MAD R4.xyz, R0.w, R1, R4;\n"
     4413    "ADD R6.xyz, R4, -R5;\n"
     4414    "MUL R4.xyz, R1, c[8].w;\n"
     4415    "SGE R4.xyz, R4, R1.w;\n"
     4416    "MAD R4.xyz, R4, R6, R5;\n"
     4417    "MAD R4.xyz, -R1, R2, R4;\n"
     4418    "SGE R3.xyz, R3, R0.w;\n"
    44554419    "MUL R2.xyz, R1, R2;\n"
    4456     "MUL R4.xyz, R0, c[8].z;\n"
    4457     "ADD R3.xyz, R3, -R2;\n"
    4458     "SGE R4.xyz, R4, R0.w;\n"
    4459     "MUL R3.xyz, R4, R3;\n"
    4460     "ADD R2.xyz, R2, R3;\n"
    44614420    "ADD R2.w, -R1, c[8].x;\n"
    4462     "MAD R0.xyz, R0, R2.w, R2;\n"
    4463     "ADD R2.x, -R0.w, c[8];\n"
    4464     "MAD R2.xyz, R1, R2.x, R0;\n"
     4421    "MAD R2.xyz, R3, R4, R2;\n"
     4422    "MAD R2.xyz, R0, R2.w, R2;\n"
     4423    "ADD R0.x, -R0.w, c[8];\n"
     4424    "MAD R2.xyz, R1, R0.x, R2;\n"
    44654425    "ADD R0.z, R0.w, R1.w;\n"
    44664426    "MAD R2.w, -R0, R1, R0.z;\n"
    4467     "ADD R0.xy, fragment.position, c[0];\n"
    4468     "MUL R0.xy, R0, c[1];\n"
     4427    "ADD R0.xy, fragment.position, c[6];\n"
     4428    "MUL R0.xy, R0, c[4];\n"
    44694429    "TEX R0, R0, texture[1], 2D;\n"
    44704430    "ADD R2, R2, -R1;\n"
    4471     "DP4 R0.x, R0, c[2];\n"
     4431    "DP4 R0.x, R0, c[7];\n"
    44724432    "MAD result.color, R0.x, R2, R1;\n"
    44734433    "END\n"
     
    44824442    "TEMP R2;\n"
    44834443    "TEMP R3;\n"
    4484     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4485     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4486     "ADD R0.xyz, R0, c[5];\n"
    4487     "RCP R0.z, R0.z;\n"
    4488     "MUL R0.xy, R0, R0.z;\n"
    4489     "MUL R0.xy, R0, c[6];\n"
     4444    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4445    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4446    "ADD R0.xyz, R0, c[3];\n"
     4447    "RCP R0.z, R0.z;\n"
     4448    "MUL R0.xy, R0, R0.z;\n"
     4449    "MUL R0.xy, R0, c[0];\n"
     4450    "ADD R0.z, R0.x, R0.y;\n"
     4451    "MUL R1.x, R0.z, c[0].z;\n"
     4452    "MUL R0.xy, fragment.position, c[5];\n"
     4453    "TEX R0, R0, texture[0], 2D;\n"
     4454    "TEX R1, R1, texture[2], 1D;\n"
     4455    "ADD R2.xyz, R1, R0;\n"
     4456    "MUL R3.xyz, R1.w, R0;\n"
     4457    "MUL R1.xyz, R1, R0.w;\n"
     4458    "MIN R1.xyz, R1, R3;\n"
     4459    "MAD R2.xyz, -R1, c[8].x, R2;\n"
     4460    "ADD R1.z, R1.w, R0.w;\n"
     4461    "MAD R2.w, -R1, R0, R1.z;\n"
     4462    "ADD R1.xy, fragment.position, c[6];\n"
     4463    "MUL R1.xy, R1, c[4];\n"
     4464    "TEX R1, R1, texture[1], 2D;\n"
     4465    "ADD R2, R2, -R0;\n"
     4466    "DP4 R1.x, R1, c[7];\n"
     4467    "MAD result.color, R1.x, R2, R0;\n"
     4468    "END\n"
     4469    ;
     4470
     4471static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION =
     4472    "!!ARBfp1.0\n"
     4473    "PARAM c[9] = { program.local[0..7],\n"
     4474    "           { 2, 1 } };\n"
     4475    "TEMP R0;\n"
     4476    "TEMP R1;\n"
     4477    "TEMP R2;\n"
     4478    "TEMP R3;\n"
     4479    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4480    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4481    "ADD R0.xyz, R0, c[3];\n"
     4482    "RCP R0.z, R0.z;\n"
     4483    "MUL R0.xy, R0, R0.z;\n"
     4484    "MUL R0.xy, R0, c[0];\n"
     4485    "ADD R0.z, R0.x, R0.y;\n"
     4486    "MUL R1.x, R0.z, c[0].z;\n"
     4487    "MUL R0.xy, fragment.position, c[5];\n"
     4488    "TEX R0, R0, texture[0], 2D;\n"
     4489    "TEX R1, R1, texture[2], 1D;\n"
     4490    "MUL R2.xyz, R1.w, R0;\n"
     4491    "MAD R3.xyz, R1, R0.w, R2;\n"
     4492    "MUL R2.xyz, R1, R0;\n"
     4493    "MAD R2.xyz, -R2, c[8].x, R3;\n"
     4494    "ADD R2.w, -R0, c[8].y;\n"
     4495    "MAD R1.xyz, R1, R2.w, R2;\n"
     4496    "ADD R2.x, -R1.w, c[8].y;\n"
     4497    "MAD R2.xyz, R0, R2.x, R1;\n"
     4498    "ADD R1.z, R1.w, R0.w;\n"
     4499    "MAD R2.w, -R1, R0, R1.z;\n"
     4500    "ADD R1.xy, fragment.position, c[6];\n"
     4501    "MUL R1.xy, R1, c[4];\n"
     4502    "TEX R1, R1, texture[1], 2D;\n"
     4503    "ADD R2, R2, -R0;\n"
     4504    "DP4 R1.x, R1, c[7];\n"
     4505    "MAD result.color, R1.x, R2, R0;\n"
     4506    "END\n"
     4507    ;
     4508
     4509static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
     4510    "!!ARBfp1.0\n"
     4511    "PARAM c[8] = { program.local[0..6],\n"
     4512    "           { 1 } };\n"
     4513    "TEMP R0;\n"
     4514    "TEMP R1;\n"
     4515    "TEMP R2;\n"
     4516    "TEMP R3;\n"
     4517    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4518    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4519    "ADD R0.xyz, R0, c[3];\n"
     4520    "RCP R0.z, R0.z;\n"
     4521    "MUL R0.xy, R0, R0.z;\n"
     4522    "MUL R0.xy, R0, c[0];\n"
    44904523    "ADD R0.x, R0, R0.y;\n"
    4491     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
     4524    "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
    44924525    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4493     "MUL R0.x, R0, c[6].z;\n"
    4494     "TEX R0, R0, texture[2], 1D;\n"
    4495     "ADD R3.xyz, R0, R1;\n"
    4496     "MUL R2.xyz, R1, R0.w;\n"
    4497     "MUL R0.xyz, R0, R1.w;\n"
    4498     "MIN R0.xyz, R0, R2;\n"
    4499     "MAD R2.xyz, -R0, c[8].x, R3;\n"
    4500     "ADD R0.z, R0.w, R1.w;\n"
    4501     "MAD R2.w, -R0, R1, R0.z;\n"
    4502     "ADD R0.xy, fragment.position, c[0];\n"
    4503     "MUL R0.xy, R0, c[1];\n"
    4504     "TEX R0, R0, texture[1], 2D;\n"
    4505     "ADD R2, R2, -R1;\n"
    4506     "DP4 R0.x, R0, c[2];\n"
    4507     "MAD result.color, R0.x, R2, R1;\n"
    4508     "END\n"
    4509     ;
    4510 
    4511 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_EXCLUSION =
    4512     "!!ARBfp1.0\n"
    4513     "PARAM c[9] = { program.local[0..7],\n"
    4514     "           { 1, 2 } };\n"
    4515     "TEMP R0;\n"
    4516     "TEMP R1;\n"
    4517     "TEMP R2;\n"
    4518     "TEMP R3;\n"
    4519     "MUL R0.xyz, fragment.position.y, c[4];\n"
    4520     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    4521     "ADD R0.xyz, R0, c[5];\n"
    4522     "RCP R0.z, R0.z;\n"
    4523     "MUL R0.xy, R0, R0.z;\n"
    4524     "MUL R0.xy, R0, c[6];\n"
    4525     "ADD R0.x, R0, R0.y;\n"
    4526     "MUL R0.x, R0, c[6].z;\n"
    4527     "MUL R1.xy, fragment.position, c[7];\n"
    4528     "TEX R1, R1, texture[0], 2D;\n"
    4529     "TEX R0, R0, texture[2], 1D;\n"
    4530     "MUL R2.xyz, R1, R0.w;\n"
    4531     "MAD R3.xyz, R0, R1.w, R2;\n"
    4532     "MUL R2.xyz, R0, R1;\n"
    4533     "MAD R2.xyz, -R2, c[8].y, R3;\n"
    4534     "ADD R2.w, -R1, c[8].x;\n"
    4535     "MAD R0.xyz, R0, R2.w, R2;\n"
    4536     "ADD R2.x, -R0.w, c[8];\n"
    4537     "MAD R2.xyz, R1, R2.x, R0;\n"
    4538     "ADD R0.z, R0.w, R1.w;\n"
    4539     "MAD R2.w, -R0, R1, R0.z;\n"
    4540     "ADD R0.xy, fragment.position, c[0];\n"
    4541     "MUL R0.xy, R0, c[1];\n"
    4542     "TEX R0, R0, texture[1], 2D;\n"
    4543     "ADD R2, R2, -R1;\n"
    4544     "DP4 R0.x, R0, c[2];\n"
    4545     "MAD result.color, R0.x, R2, R1;\n"
    4546     "END\n"
    4547     ;
    4548 
    4549 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    4550     "!!ARBfp1.0\n"
    4551     "PARAM c[8] = { program.local[0..4],\n"
    4552     "           { 1 },\n"
    4553     "           program.local[6..7] };\n"
    4554     "TEMP R0;\n"
    4555     "TEMP R1;\n"
    4556     "TEMP R2;\n"
    4557     "TEMP R3;\n"
    4558     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4559     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4560     "ADD R0.xyz, R0, c[2];\n"
    4561     "RCP R0.z, R0.z;\n"
    4562     "MUL R0.xy, R0, R0.z;\n"
    4563     "MUL R0.xy, R0, c[3];\n"
     4526    "MUL R2.xyz, R1, c[4].y;\n"
     4527    "MUL R0.x, R0, c[0].z;\n"
     4528    "TEX R0, R0, texture[1], 1D;\n"
     4529    "MUL R3.xyz, R0.w, R2;\n"
     4530    "MUL R2.xyz, R0, c[4].x;\n"
     4531    "MAD R2.xyz, R1.w, R2, R3;\n"
     4532    "ADD R2.w, -R1, c[7].x;\n"
     4533    "MUL R0.xyz, R0, c[5].y;\n"
     4534    "MAD R0.xyz, R2.w, R0, R2;\n"
     4535    "ADD R2.x, -R0.w, c[7];\n"
     4536    "MUL R1.xyz, R1, c[5].z;\n"
     4537    "MAD result.color.xyz, R2.x, R1, R0;\n"
     4538    "MUL R0.x, R0.w, R1.w;\n"
     4539    "MUL R0.z, R1.w, R2.x;\n"
     4540    "MUL R0.y, R0.w, R2.w;\n"
     4541    "DP3 result.color.w, R0, c[5];\n"
     4542    "END\n"
     4543    ;
     4544
     4545static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY_NOMASK =
     4546    "!!ARBfp1.0\n"
     4547    "PARAM c[6] = { program.local[0..4],\n"
     4548    "           { 1 } };\n"
     4549    "TEMP R0;\n"
     4550    "TEMP R1;\n"
     4551    "TEMP R2;\n"
     4552    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4553    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4554    "ADD R0.xyz, R0, c[3];\n"
     4555    "RCP R0.z, R0.z;\n"
     4556    "MUL R0.xy, R0, R0.z;\n"
     4557    "MUL R0.xy, R0, c[0];\n"
    45644558    "ADD R0.x, R0, R0.y;\n"
    45654559    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    45664560    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4567     "MUL R2.xyz, R1, c[7].y;\n"
    4568     "MUL R0.x, R0, c[3].z;\n"
    4569     "TEX R0, R0, texture[1], 1D;\n"
    4570     "MUL R3.xyz, R2, R0.w;\n"
    4571     "MUL R2.xyz, R0, c[7].x;\n"
    4572     "MAD R2.xyz, R2, R1.w, R3;\n"
    4573     "MUL R0.xyz, R0, c[6].y;\n"
    4574     "ADD R2.w, -R1, c[5].x;\n"
    4575     "MAD R0.xyz, R0, R2.w, R2;\n"
    4576     "ADD R2.x, -R0.w, c[5];\n"
    4577     "MUL R1.xyz, R1, c[6].z;\n"
    4578     "MAD result.color.xyz, R1, R2.x, R0;\n"
    4579     "ADD R0.y, -R1.w, c[5].x;\n"
    4580     "MUL R0.x, R0.w, R1.w;\n"
    4581     "MUL R0.z, R1.w, R2.x;\n"
    4582     "MUL R0.y, R0.w, R0;\n"
    4583     "DP3 result.color.w, R0, c[6];\n"
    4584     "END\n"
    4585     ;
    4586 
    4587 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_LINEAR_COMPOSITION_MODES_MULTIPLY_NOMASK =
    4588     "!!ARBfp1.0\n"
    4589     "PARAM c[6] = { program.local[0..4],\n"
    4590     "           { 1 } };\n"
    4591     "TEMP R0;\n"
    4592     "TEMP R1;\n"
    4593     "TEMP R2;\n"
    4594     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4595     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4596     "ADD R0.xyz, R0, c[2];\n"
    4597     "RCP R0.z, R0.z;\n"
    4598     "MUL R0.xy, R0, R0.z;\n"
    4599     "MUL R0.xy, R0, c[3];\n"
    4600     "ADD R0.x, R0, R0.y;\n"
    4601     "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    4602     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4603     "MUL R0.x, R0, c[3].z;\n"
     4561    "MUL R0.x, R0, c[0].z;\n"
    46044562    "TEX R0, R0, texture[1], 1D;\n"
    46054563    "ADD R2.x, -R1.w, c[5];\n"
     
    46194577    "TEMP R1;\n"
    46204578    "TEMP R2;\n"
    4621     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4622     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4623     "ADD R0.xyz, R0, c[2];\n"
    4624     "RCP R0.z, R0.z;\n"
    4625     "MUL R0.xy, R0, R0.z;\n"
    4626     "MUL R0.xy, R0, c[3];\n"
     4579    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4580    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4581    "ADD R0.xyz, R0, c[3];\n"
     4582    "RCP R0.z, R0.z;\n"
     4583    "MUL R0.xy, R0, R0.z;\n"
     4584    "MUL R0.xy, R0, c[0];\n"
    46274585    "ADD R0.x, R0, R0.y;\n"
    46284586    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    46294587    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    4630     "MUL R0.x, R0, c[3].z;\n"
     4588    "MUL R0.x, R0, c[0].z;\n"
    46314589    "TEX R0, R0, texture[1], 1D;\n"
    46324590    "ADD R2, R0, R1;\n"
     
    46434601    "TEMP R2;\n"
    46444602    "TEMP R3;\n"
    4645     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4646     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4647     "ADD R0.xyz, R0, c[2];\n"
    4648     "RCP R0.z, R0.z;\n"
    4649     "MUL R0.xy, R0, R0.z;\n"
    4650     "MUL R0.xy, R0, c[3];\n"
     4603    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4604    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4605    "ADD R0.xyz, R0, c[3];\n"
     4606    "RCP R0.z, R0.z;\n"
     4607    "MUL R0.xy, R0, R0.z;\n"
     4608    "MUL R0.xy, R0, c[0];\n"
    46514609    "ADD R0.x, R0, R0.y;\n"
    4652     "MUL R0.x, R0, c[3].z;\n"
     4610    "MUL R0.x, R0, c[0].z;\n"
    46534611    "TEX R0, R0, texture[1], 1D;\n"
    46544612    "MUL R1.xy, fragment.position, c[4];\n"
     
    46844642    "TEMP R2;\n"
    46854643    "TEMP R3;\n"
    4686     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4687     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4688     "ADD R0.xyz, R0, c[2];\n"
    4689     "RCP R0.z, R0.z;\n"
    4690     "MUL R0.xy, R0, R0.z;\n"
    4691     "MUL R0.xy, R0, c[3];\n"
     4644    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4645    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4646    "ADD R0.xyz, R0, c[3];\n"
     4647    "RCP R0.z, R0.z;\n"
     4648    "MUL R0.xy, R0, R0.z;\n"
     4649    "MUL R0.xy, R0, c[0];\n"
    46924650    "ADD R0.x, R0, R0.y;\n"
    4693     "MUL R0.x, R0, c[3].z;\n"
    4694     "MUL R1.xy, fragment.position, c[4];\n"
    4695     "TEX R1, R1, texture[0], 2D;\n"
     4651    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     4652    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4653    "MUL R0.x, R0, c[0].z;\n"
    46964654    "TEX R0, R0, texture[1], 1D;\n"
    46974655    "MUL R2.xyz, R0, R1.w;\n"
    4698     "MUL R3.xyz, R1, R0.w;\n"
     4656    "MUL R3.xyz, R0.w, R1;\n"
    46994657    "MIN R2.xyz, R2, R3;\n"
    47004658    "ADD R2.w, -R1, c[5].x;\n"
     
    47154673    "TEMP R2;\n"
    47164674    "TEMP R3;\n"
    4717     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4718     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4719     "ADD R0.xyz, R0, c[2];\n"
    4720     "RCP R0.z, R0.z;\n"
    4721     "MUL R0.xy, R0, R0.z;\n"
    4722     "MUL R0.xy, R0, c[3];\n"
     4675    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4676    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4677    "ADD R0.xyz, R0, c[3];\n"
     4678    "RCP R0.z, R0.z;\n"
     4679    "MUL R0.xy, R0, R0.z;\n"
     4680    "MUL R0.xy, R0, c[0];\n"
    47234681    "ADD R0.x, R0, R0.y;\n"
    4724     "MUL R0.x, R0, c[3].z;\n"
    4725     "MUL R1.xy, fragment.position, c[4];\n"
    4726     "TEX R1, R1, texture[0], 2D;\n"
     4682    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     4683    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4684    "MUL R0.x, R0, c[0].z;\n"
    47274685    "TEX R0, R0, texture[1], 1D;\n"
    47284686    "MUL R2.xyz, R0, R1.w;\n"
    4729     "MUL R3.xyz, R1, R0.w;\n"
     4687    "MUL R3.xyz, R0.w, R1;\n"
    47304688    "MAX R2.xyz, R2, R3;\n"
    47314689    "ADD R2.w, -R1, c[5].x;\n"
     
    47414699    "!!ARBfp1.0\n"
    47424700    "PARAM c[6] = { program.local[0..4],\n"
    4743     "           { 1, 1e-06 } };\n"
    4744     "TEMP R0;\n"
    4745     "TEMP R1;\n"
    4746     "TEMP R2;\n"
    4747     "TEMP R3;\n"
    4748     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4749     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4750     "ADD R0.xyz, R0, c[2];\n"
    4751     "RCP R0.z, R0.z;\n"
    4752     "MUL R0.xy, R0, R0.z;\n"
    4753     "MUL R0.xy, R0, c[3];\n"
     4701    "           { 1, 1e-006 } };\n"
     4702    "TEMP R0;\n"
     4703    "TEMP R1;\n"
     4704    "TEMP R2;\n"
     4705    "TEMP R3;\n"
     4706    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4707    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4708    "ADD R0.xyz, R0, c[3];\n"
     4709    "RCP R0.z, R0.z;\n"
     4710    "MUL R0.xy, R0, R0.z;\n"
     4711    "MUL R0.xy, R0, c[0];\n"
    47544712    "ADD R0.x, R0, R0.y;\n"
    4755     "MUL R0.x, R0, c[3].z;\n"
     4713    "MUL R0.x, R0, c[0].z;\n"
    47564714    "TEX R0, R0, texture[1], 1D;\n"
    47574715    "MAX R1.x, R0.w, c[5].y;\n"
     
    47654723    "ADD R2.w, -R1, c[5].x;\n"
    47664724    "MAD R2.xyz, R0, R2.w, R2;\n"
    4767     "MUL R1.xyz, R1, R0.w;\n"
     4725    "MUL R1.xyz, R0.w, R1;\n"
    47684726    "MAD R0.xyz, R0, R1.w, R1;\n"
    47694727    "MUL R2.w, R0, R1;\n"
     
    47844742    "!!ARBfp1.0\n"
    47854743    "PARAM c[6] = { program.local[0..4],\n"
    4786     "           { 1, 9.9999997e-06 } };\n"
     4744    "           { 1, 9.9999997e-006 } };\n"
    47874745    "TEMP R0;\n"
    47884746    "TEMP R1;\n"
     
    47914749    "TEMP R4;\n"
    47924750    "TEMP R5;\n"
    4793     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4794     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4795     "ADD R0.xyz, R0, c[2];\n"
    4796     "RCP R0.z, R0.z;\n"
    4797     "MUL R0.xy, R0, R0.z;\n"
    4798     "MUL R0.xy, R0, c[3];\n"
     4751    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4752    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4753    "ADD R0.xyz, R0, c[3];\n"
     4754    "RCP R0.z, R0.z;\n"
     4755    "MUL R0.xy, R0, R0.z;\n"
     4756    "MUL R0.xy, R0, c[0];\n"
    47994757    "ADD R0.x, R0, R0.y;\n"
    4800     "MUL R0.x, R0, c[3].z;\n"
     4758    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     4759    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4760    "MUL R0.x, R0, c[0].z;\n"
    48014761    "TEX R0, R0, texture[1], 1D;\n"
    4802     "MUL R1.xy, fragment.position, c[4];\n"
    4803     "TEX R1, R1, texture[0], 2D;\n"
    4804     "MUL R2.xyz, R1, R0.w;\n"
     4762    "MUL R2.xyz, R0.w, R1;\n"
    48054763    "MAD R3.xyz, R0, R1.w, R2;\n"
    48064764    "ADD R2.w, -R1, c[5].x;\n"
     
    48154773    "MAD R2.xyz, R4, R2, R5;\n"
    48164774    "MUL R4.xyz, R1, R3.w;\n"
     4775    "MAD R1.xyz, R1, R3.w, R2;\n"
    48174776    "MAD R0.xyz, R0, R2.w, R4;\n"
    4818     "ADD R3.w, -R0, c[5].x;\n"
    4819     "MAD R1.xyz, R1, R3.w, R2;\n"
    48204777    "MUL R2.x, R0.w, R1.w;\n"
    48214778    "ADD R2.w, R0, R1;\n"
     
    48364793    "TEMP R3;\n"
    48374794    "TEMP R4;\n"
    4838     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4839     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4840     "ADD R0.xyz, R0, c[2];\n"
    4841     "RCP R0.z, R0.z;\n"
    4842     "MUL R0.xy, R0, R0.z;\n"
    4843     "MUL R0.xy, R0, c[3];\n"
     4795    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4796    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4797    "ADD R0.xyz, R0, c[3];\n"
     4798    "RCP R0.z, R0.z;\n"
     4799    "MUL R0.xy, R0, R0.z;\n"
     4800    "MUL R0.xy, R0, c[0];\n"
    48444801    "ADD R0.x, R0, R0.y;\n"
    4845     "MUL R0.x, R0, c[3].z;\n"
     4802    "MUL R0.x, R0, c[0].z;\n"
    48464803    "TEX R0, R0, texture[1], 1D;\n"
    48474804    "MUL R1.xy, fragment.position, c[4];\n"
     
    48724829    "!!ARBfp1.0\n"
    48734830    "PARAM c[7] = { program.local[0..4],\n"
    4874     "           { 1, 9.9999997e-06, 2, 8 },\n"
    4875     "           { 3 } };\n"
     4831    "           { 1, 2, 9.9999997e-006, 4 },\n"
     4832    "           { 16, 12, 3 } };\n"
    48764833    "TEMP R0;\n"
    48774834    "TEMP R1;\n"
     
    48814838    "TEMP R5;\n"
    48824839    "TEMP R6;\n"
    4883     "MUL R2.xyz, fragment.position.y, c[1];\n"
    4884     "MAD R3.xyz, fragment.position.x, c[0], R2;\n"
    4885     "MUL R0.xy, fragment.position, c[4];\n"
    4886     "TEX R1, R0, texture[0], 2D;\n"
    4887     "MAX R0.x, R1.w, c[5].y;\n"
    4888     "RCP R2.w, R0.x;\n"
    4889     "MUL R0.xyz, R1, R2.w;\n"
    4890     "RSQ R0.w, R0.x;\n"
    4891     "RSQ R2.y, R0.y;\n"
    4892     "ADD R3.xyz, R3, c[2];\n"
    4893     "RCP R2.x, R0.w;\n"
    4894     "RCP R0.w, R3.z;\n"
    4895     "MUL R3.xy, R3, R0.w;\n"
    4896     "RSQ R0.w, R0.z;\n"
    4897     "RCP R2.z, R0.w;\n"
    4898     "RCP R2.y, R2.y;\n"
    4899     "MAD R6.xyz, R2, R1.w, -R1;\n"
    4900     "MUL R2.xyz, -R0, c[5].w;\n"
    4901     "ADD R5.xyz, R2, c[6].x;\n"
    4902     "MAD R2.xyz, -R1, R2.w, c[5].x;\n"
    4903     "MUL R3.xy, R3, c[3];\n"
    4904     "ADD R0.w, R3.x, R3.y;\n"
    4905     "MUL R0.w, R0, c[3].z;\n"
    4906     "TEX R0, R0.w, texture[1], 1D;\n"
    4907     "MAD R3.xyz, R0, c[5].z, -R0.w;\n"
    4908     "MUL R4.xyz, R2, R3;\n"
    4909     "MAD R4.xyz, -R4, R5, R0.w;\n"
    4910     "MUL R5.xyz, R6, R3;\n"
    4911     "MAD R2.xyz, -R2, R3, R0.w;\n"
    4912     "MAD R6.xyz, R1, R0.w, R5;\n"
    4913     "MUL R4.xyz, R1, R4;\n"
    4914     "MUL R5.xyz, R1, c[5].w;\n"
    4915     "ADD R6.xyz, R6, -R4;\n"
    4916     "SGE R5.xyz, R5, R1.w;\n"
    4917     "MUL R5.xyz, R5, R6;\n"
    4918     "ADD R3.xyz, R4, R5;\n"
     4840    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4841    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4842    "ADD R0.xyz, R0, c[3];\n"
     4843    "RCP R0.z, R0.z;\n"
     4844    "MUL R0.xy, R0, R0.z;\n"
     4845    "MUL R0.xy, R0, c[0];\n"
     4846    "ADD R0.x, R0, R0.y;\n"
     4847    "MUL R1.xy, fragment.position, c[4];\n"
     4848    "TEX R1, R1, texture[0], 2D;\n"
     4849    "MAX R0.z, R1.w, c[5];\n"
     4850    "RCP R0.z, R0.z;\n"
     4851    "MUL R3.xyz, R1, R0.z;\n"
     4852    "MAD R2.xyz, R3, c[6].x, -c[6].y;\n"
     4853    "MUL R0.x, R0, c[0].z;\n"
     4854    "TEX R0, R0, texture[1], 1D;\n"
     4855    "MAD R4.xyz, R3, R2, c[6].z;\n"
     4856    "MAD R2.xyz, R0, c[5].y, -R0.w;\n"
     4857    "MUL R5.xyz, R1.w, R2;\n"
     4858    "MUL R6.xyz, R5, R4;\n"
     4859    "RSQ R2.w, R3.x;\n"
     4860    "RCP R4.x, R2.w;\n"
     4861    "RSQ R2.w, R3.y;\n"
     4862    "RSQ R3.w, R3.z;\n"
     4863    "RCP R4.y, R2.w;\n"
     4864    "RCP R4.z, R3.w;\n"
     4865    "ADD R4.xyz, -R3, R4;\n"
     4866    "MUL R6.xyz, R3, R6;\n"
     4867    "MUL R4.xyz, R5, R4;\n"
     4868    "ADD R3.xyz, -R3, c[5].x;\n"
     4869    "MAD R2.xyz, R2, R3, R0.w;\n"
     4870    "MUL R3.xyz, R0, c[5].y;\n"
     4871    "MAD R5.xyz, R0.w, R1, R6;\n"
     4872    "MAD R4.xyz, R0.w, R1, R4;\n"
     4873    "ADD R6.xyz, R4, -R5;\n"
     4874    "MUL R4.xyz, R1, c[5].w;\n"
     4875    "SGE R4.xyz, R4, R1.w;\n"
     4876    "MAD R4.xyz, R4, R6, R5;\n"
     4877    "MAD R4.xyz, -R1, R2, R4;\n"
    49194878    "MUL R2.xyz, R1, R2;\n"
    4920     "MUL R4.xyz, R0, c[5].z;\n"
    4921     "ADD R3.xyz, R3, -R2;\n"
    4922     "SGE R4.xyz, R4, R0.w;\n"
    4923     "MUL R3.xyz, R4, R3;\n"
    4924     "ADD R2.xyz, R2, R3;\n"
     4879    "SGE R3.xyz, R3, R0.w;\n"
     4880    "MAD R2.xyz, R3, R4, R2;\n"
    49254881    "ADD R2.w, -R1, c[5].x;\n"
    4926     "MAD R0.xyz, R0, R2.w, R2;\n"
    4927     "ADD R2.x, R0.w, R1.w;\n"
    4928     "ADD R2.y, -R0.w, c[5].x;\n"
    4929     "MAD result.color.xyz, R1, R2.y, R0;\n"
    4930     "MAD result.color.w, -R0, R1, R2.x;\n"
     4882    "MAD R2.xyz, R0, R2.w, R2;\n"
     4883    "ADD R0.x, R0.w, R1.w;\n"
     4884    "ADD R0.y, -R0.w, c[5].x;\n"
     4885    "MAD result.color.xyz, R1, R0.y, R2;\n"
     4886    "MAD result.color.w, -R0, R1, R0.x;\n"
    49314887    "END\n"
    49324888    ;
     
    49404896    "TEMP R2;\n"
    49414897    "TEMP R3;\n"
    4942     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4943     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4944     "ADD R0.xyz, R0, c[2];\n"
    4945     "RCP R0.z, R0.z;\n"
    4946     "MUL R0.xy, R0, R0.z;\n"
    4947     "MUL R0.xy, R0, c[3];\n"
     4898    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4899    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4900    "ADD R0.xyz, R0, c[3];\n"
     4901    "RCP R0.z, R0.z;\n"
     4902    "MUL R0.xy, R0, R0.z;\n"
     4903    "MUL R0.xy, R0, c[0];\n"
    49484904    "ADD R0.x, R0, R0.y;\n"
    4949     "MUL R0.x, R0, c[3].z;\n"
    4950     "MUL R1.xy, fragment.position, c[4];\n"
     4905    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     4906    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4907    "MUL R0.x, R0, c[0].z;\n"
    49514908    "TEX R0, R0, texture[1], 1D;\n"
    4952     "TEX R1, R1, texture[0], 2D;\n"
    49534909    "MUL R2.xyz, R0, R1.w;\n"
    4954     "MUL R3.xyz, R1, R0.w;\n"
     4910    "MUL R3.xyz, R0.w, R1;\n"
    49554911    "ADD R0.xyz, R0, R1;\n"
    49564912    "MIN R2.xyz, R2, R3;\n"
     
    49644920    "!!ARBfp1.0\n"
    49654921    "PARAM c[6] = { program.local[0..4],\n"
    4966     "           { 1, 2 } };\n"
    4967     "TEMP R0;\n"
    4968     "TEMP R1;\n"
    4969     "TEMP R2;\n"
    4970     "TEMP R3;\n"
    4971     "MUL R0.xyz, fragment.position.y, c[1];\n"
    4972     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    4973     "ADD R0.xyz, R0, c[2];\n"
    4974     "RCP R0.z, R0.z;\n"
    4975     "MUL R0.xy, R0, R0.z;\n"
    4976     "MUL R0.xy, R0, c[3];\n"
     4922    "           { 2, 1 } };\n"
     4923    "TEMP R0;\n"
     4924    "TEMP R1;\n"
     4925    "TEMP R2;\n"
     4926    "TEMP R3;\n"
     4927    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4928    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4929    "ADD R0.xyz, R0, c[3];\n"
     4930    "RCP R0.z, R0.z;\n"
     4931    "MUL R0.xy, R0, R0.z;\n"
     4932    "MUL R0.xy, R0, c[0];\n"
    49774933    "ADD R0.x, R0, R0.y;\n"
    4978     "MUL R0.x, R0, c[3].z;\n"
    4979     "MUL R1.xy, fragment.position, c[4];\n"
    4980     "TEX R1, R1, texture[0], 2D;\n"
     4934    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     4935    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     4936    "MUL R0.x, R0, c[0].z;\n"
    49814937    "TEX R0, R0, texture[1], 1D;\n"
    4982     "MUL R2.xyz, R1, R0.w;\n"
     4938    "MUL R2.xyz, R0.w, R1;\n"
    49834939    "MAD R3.xyz, R0, R1.w, R2;\n"
    49844940    "MUL R2.xyz, R0, R1;\n"
    4985     "MAD R2.xyz, -R2, c[5].y, R3;\n"
    4986     "ADD R2.w, -R1, c[5].x;\n"
     4941    "MAD R2.xyz, -R2, c[5].x, R3;\n"
     4942    "ADD R2.w, -R1, c[5].y;\n"
    49874943    "MAD R0.xyz, R0, R2.w, R2;\n"
    49884944    "ADD R2.x, R0.w, R1.w;\n"
    4989     "ADD R2.y, -R0.w, c[5].x;\n"
     4945    "ADD R2.y, -R0.w, c[5];\n"
    49904946    "MAD result.color.xyz, R1, R2.y, R0;\n"
    49914947    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    49984954    "TEMP R0;\n"
    49994955    "TEMP R1;\n"
    5000     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5001     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5002     "ADD R0.xyz, R0, c[2];\n"
     4956    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4957    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4958    "ADD R0.xyz, R0, c[3];\n"
    50034959    "RCP R0.z, R0.z;\n"
    50044960    "MUL R0.zw, R0.xyxy, R0.z;\n"
    5005     "MUL R0.zw, R0, c[3].xyxy;\n"
     4961    "MUL R0.zw, R0, c[0].xyxy;\n"
    50064962    "ADD R1.x, R0.z, R0.w;\n"
    5007     "ADD R0.xy, fragment.position, c[4];\n"
    5008     "MUL R0.xy, R0, c[5];\n"
     4963    "ADD R0.xy, fragment.position, c[5];\n"
     4964    "MUL R0.xy, R0, c[4];\n"
    50094965    "TEX R0, R0, texture[0], 2D;\n"
    50104966    "DP4 R1.y, R0, c[6];\n"
    5011     "MUL R1.x, R1, c[3].z;\n"
     4967    "MUL R1.x, R1, c[0].z;\n"
    50124968    "TEX R0, R1, texture[1], 1D;\n"
    50134969    "MUL result.color, R0, R1.y;\n"
     
    50194975    "PARAM c[4] = { program.local[0..3] };\n"
    50204976    "TEMP R0;\n"
    5021     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5022     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5023     "ADD R0.xyz, R0, c[2];\n"
    5024     "RCP R0.z, R0.z;\n"
    5025     "MUL R0.xy, R0, R0.z;\n"
    5026     "MUL R0.xy, R0, c[3];\n"
     4977    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4978    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4979    "ADD R0.xyz, R0, c[3];\n"
     4980    "RCP R0.z, R0.z;\n"
     4981    "MUL R0.xy, R0, R0.z;\n"
     4982    "MUL R0.xy, R0, c[0];\n"
    50274983    "ADD R0.x, R0, R0.y;\n"
    5028     "MUL R0.x, R0, c[3].z;\n"
     4984    "MUL R0.x, R0, c[0].z;\n"
    50294985    "TEX result.color, R0, texture[0], 1D;\n"
    50304986    "END\n"
     
    50334989static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    50344990    "!!ARBfp1.0\n"
    5035     "PARAM c[11] = { program.local[0..7],\n"
    5036     "           { 1 },\n"
    5037     "           program.local[9..10] };\n"
    5038     "TEMP R0;\n"
    5039     "TEMP R1;\n"
    5040     "TEMP R2;\n"
    5041     "TEMP R3;\n"
    5042     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5043     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5044     "ADD R0.xyz, R0, c[5];\n"
    5045     "RCP R0.z, R0.z;\n"
    5046     "MUL R0.xy, R0, R0.z;\n"
    5047     "MUL R0.xy, R0, c[6];\n"
    5048     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    5049     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5050     "MOV R0.y, -R0;\n"
    5051     "TEX R0, R0, texture[2], 2D;\n"
    5052     "MUL R2.xyz, R1, c[10].y;\n"
    5053     "MUL R3.xyz, R2, R0.w;\n"
    5054     "MUL R2.xyz, R0, c[10].x;\n"
    5055     "MAD R2.xyz, R2, R1.w, R3;\n"
    5056     "ADD R3.xy, fragment.position, c[0];\n"
    5057     "MUL R0.xyz, R0, c[9].y;\n"
    5058     "ADD R2.w, -R1, c[8].x;\n"
    5059     "MAD R2.xyz, R0, R2.w, R2;\n"
    5060     "ADD R2.w, -R0, c[8].x;\n"
    5061     "MUL R0.xyz, R1, c[9].z;\n"
    5062     "MAD R2.xyz, R0, R2.w, R2;\n"
    5063     "ADD R0.y, -R1.w, c[8].x;\n"
    5064     "MUL R0.z, R1.w, R2.w;\n"
    5065     "MUL R0.x, R0.w, R1.w;\n"
    5066     "MUL R0.y, R0.w, R0;\n"
    5067     "DP3 R2.w, R0, c[9];\n"
    5068     "MUL R3.xy, R3, c[1];\n"
    5069     "TEX R0, R3, texture[1], 2D;\n"
    5070     "ADD R2, R2, -R1;\n"
    5071     "DP4 R0.x, R0, c[2];\n"
    5072     "MAD result.color, R0.x, R2, R1;\n"
     4991    "PARAM c[11] = { program.local[0..9],\n"
     4992    "           { 1 } };\n"
     4993    "TEMP R0;\n"
     4994    "TEMP R1;\n"
     4995    "TEMP R2;\n"
     4996    "TEMP R3;\n"
     4997    "MUL R0.xyz, fragment.position.y, c[2];\n"
     4998    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     4999    "ADD R1.xyz, R0, c[3];\n"
     5000    "RCP R0.z, R1.z;\n"
     5001    "MUL R1.xy, R1, R0.z;\n"
     5002    "MUL R0.xy, fragment.position, c[7];\n"
     5003    "TEX R0, R0, texture[0], 2D;\n"
     5004    "MUL R1.xy, R1, c[0];\n"
     5005    "TEX R1, R1, texture[2], 2D;\n"
     5006    "MUL R2.xyz, R0, c[4].y;\n"
     5007    "MUL R3.xyz, R1.w, R2;\n"
     5008    "MUL R2.xyz, R1, c[4].x;\n"
     5009    "MAD R2.xyz, R0.w, R2, R3;\n"
     5010    "ADD R3.xy, fragment.position, c[8];\n"
     5011    "ADD R2.w, -R0, c[10].x;\n"
     5012    "MUL R1.xyz, R1, c[5].y;\n"
     5013    "MAD R2.xyz, R2.w, R1, R2;\n"
     5014    "MUL R1.xyz, R0, c[5].z;\n"
     5015    "ADD R3.z, -R1.w, c[10].x;\n"
     5016    "MAD R2.xyz, R3.z, R1, R2;\n"
     5017    "MUL R1.y, R1.w, R2.w;\n"
     5018    "MUL R1.x, R1.w, R0.w;\n"
     5019    "MUL R1.z, R0.w, R3;\n"
     5020    "DP3 R2.w, R1, c[5];\n"
     5021    "MUL R3.xy, R3, c[6];\n"
     5022    "TEX R1, R3, texture[1], 2D;\n"
     5023    "ADD R2, R2, -R0;\n"
     5024    "DP4 R1.x, R1, c[9];\n"
     5025    "MAD result.color, R1.x, R2, R0;\n"
    50735026    "END\n"
    50745027    ;
     
    50815034    "TEMP R1;\n"
    50825035    "TEMP R2;\n"
    5083     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5084     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5085     "ADD R0.xyz, R0, c[5];\n"
    5086     "RCP R1.x, R0.z;\n"
    5087     "MUL R0.xy, R0, R1.x;\n"
    5088     "MUL R0.xy, R0, c[6];\n"
    5089     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    5090     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5091     "MOV R0.y, -R0;\n"
    5092     "TEX R0, R0, texture[2], 2D;\n"
     5036    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5037    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5038    "ADD R1.xyz, R0, c[3];\n"
     5039    "RCP R0.z, R1.z;\n"
     5040    "MUL R1.xy, R1, R0.z;\n"
     5041    "MUL R0.xy, fragment.position, c[5];\n"
     5042    "TEX R0, R0, texture[0], 2D;\n"
     5043    "MUL R1.xy, R1, c[0];\n"
     5044    "TEX R1, R1, texture[2], 2D;\n"
     5045    "ADD R2.x, -R0.w, c[8];\n"
     5046    "MUL R2.xyz, R1, R2.x;\n"
     5047    "MAD R1.xyz, R1, R0, R2;\n"
    50935048    "ADD R2.x, -R1.w, c[8];\n"
    5094     "MUL R2.xyz, R0, R2.x;\n"
    5095     "MAD R0.xyz, R0, R1, R2;\n"
    5096     "ADD R2.x, -R0.w, c[8];\n"
    5097     "MAD R2.xyz, R1, R2.x, R0;\n"
    5098     "ADD R0.z, R0.w, R1.w;\n"
    5099     "MAD R2.w, -R0, R1, R0.z;\n"
    5100     "ADD R0.xy, fragment.position, c[0];\n"
    5101     "MUL R0.xy, R0, c[1];\n"
    5102     "TEX R0, R0, texture[1], 2D;\n"
    5103     "ADD R2, R2, -R1;\n"
    5104     "DP4 R0.x, R0, c[2];\n"
    5105     "MAD result.color, R0.x, R2, R1;\n"
     5049    "MAD R2.xyz, R0, R2.x, R1;\n"
     5050    "ADD R1.z, R1.w, R0.w;\n"
     5051    "MAD R2.w, -R1, R0, R1.z;\n"
     5052    "ADD R1.xy, fragment.position, c[6];\n"
     5053    "MUL R1.xy, R1, c[4];\n"
     5054    "TEX R1, R1, texture[1], 2D;\n"
     5055    "ADD R2, R2, -R0;\n"
     5056    "DP4 R1.x, R1, c[7];\n"
     5057    "MAD result.color, R1.x, R2, R0;\n"
    51065058    "END\n"
    51075059    ;
     
    51145066    "TEMP R2;\n"
    51155067    "TEMP R3;\n"
    5116     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5117     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5118     "ADD R0.xyz, R0, c[5];\n"
    5119     "RCP R0.z, R0.z;\n"
    5120     "MUL R0.xy, R0, R0.z;\n"
    5121     "MUL R0.xy, R0, c[6];\n"
    5122     "MOV R0.y, -R0;\n"
    5123     "MUL R1.xy, fragment.position, c[7];\n"
    5124     "ADD R3.xy, fragment.position, c[0];\n"
    5125     "TEX R1, R1, texture[0], 2D;\n"
    5126     "TEX R0, R0, texture[2], 2D;\n"
    5127     "ADD R2, R0, R1;\n"
    5128     "MAD R2, -R0, R1, R2;\n"
    5129     "MUL R3.xy, R3, c[1];\n"
    5130     "TEX R0, R3, texture[1], 2D;\n"
    5131     "ADD R2, R2, -R1;\n"
    5132     "DP4 R0.x, R0, c[2];\n"
    5133     "MAD result.color, R0.x, R2, R1;\n"
     5068    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5069    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5070    "ADD R0.xyz, R0, c[3];\n"
     5071    "RCP R0.z, R0.z;\n"
     5072    "MUL R0.xy, R0, R0.z;\n"
     5073    "MUL R0.zw, R0.xyxy, c[0].xyxy;\n"
     5074    "ADD R3.xy, fragment.position, c[6];\n"
     5075    "TEX R1, R0.zwzw, texture[2], 2D;\n"
     5076    "MUL R0.xy, fragment.position, c[5];\n"
     5077    "TEX R0, R0, texture[0], 2D;\n"
     5078    "ADD R2, R1, R0;\n"
     5079    "MAD R2, -R1, R0, R2;\n"
     5080    "MUL R3.xy, R3, c[4];\n"
     5081    "TEX R1, R3, texture[1], 2D;\n"
     5082    "ADD R2, R2, -R0;\n"
     5083    "DP4 R1.x, R1, c[7];\n"
     5084    "MAD result.color, R1.x, R2, R0;\n"
    51345085    "END\n"
    51355086    ;
     
    51445095    "TEMP R3;\n"
    51455096    "TEMP R4;\n"
    5146     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5147     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5148     "ADD R0.xyz, R0, c[5];\n"
    5149     "RCP R0.z, R0.z;\n"
    5150     "MUL R0.xy, R0, R0.z;\n"
    5151     "MUL R0.xy, R0, c[6];\n"
    5152     "MOV R0.y, -R0;\n"
     5097    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5098    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5099    "ADD R0.xyz, R0, c[3];\n"
     5100    "RCP R0.z, R0.z;\n"
     5101    "MUL R0.xy, R0, R0.z;\n"
     5102    "MUL R0.xy, R0, c[0];\n"
    51535103    "TEX R0, R0, texture[2], 2D;\n"
    5154     "MUL R1.xy, fragment.position, c[7];\n"
     5104    "MUL R1.xy, fragment.position, c[5];\n"
    51555105    "TEX R1, R1, texture[0], 2D;\n"
    51565106    "ADD R2.w, -R1, c[8].y;\n"
     
    51735123    "ADD R0.z, R0.w, R1.w;\n"
    51745124    "MAD R2.w, -R0, R1, R0.z;\n"
    5175     "ADD R0.xy, fragment.position, c[0];\n"
    5176     "MUL R0.xy, R0, c[1];\n"
     5125    "ADD R0.xy, fragment.position, c[6];\n"
     5126    "MUL R0.xy, R0, c[4];\n"
    51775127    "TEX R0, R0, texture[1], 2D;\n"
    51785128    "ADD R2, R2, -R1;\n"
    5179     "DP4 R0.x, R0, c[2];\n"
     5129    "DP4 R0.x, R0, c[7];\n"
    51805130    "MAD result.color, R0.x, R2, R1;\n"
    51815131    "END\n"
     
    51905140    "TEMP R2;\n"
    51915141    "TEMP R3;\n"
    5192     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5193     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5194     "ADD R0.xyz, R0, c[5];\n"
    5195     "RCP R0.z, R0.z;\n"
    5196     "MUL R0.xy, R0, R0.z;\n"
    5197     "MUL R0.xy, R0, c[6];\n"
    5198     "MOV R0.y, -R0;\n"
    5199     "MUL R1.xy, fragment.position, c[7];\n"
    5200     "TEX R1, R1, texture[0], 2D;\n"
    5201     "TEX R0, R0, texture[2], 2D;\n"
    5202     "MUL R3.xyz, R1, R0.w;\n"
    5203     "MUL R2.xyz, R0, R1.w;\n"
     5142    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5143    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5144    "ADD R0.xyz, R0, c[3];\n"
     5145    "RCP R0.z, R0.z;\n"
     5146    "MUL R0.zw, R0.xyxy, R0.z;\n"
     5147    "MUL R1.xy, R0.zwzw, c[0];\n"
     5148    "MUL R0.xy, fragment.position, c[5];\n"
     5149    "TEX R0, R0, texture[0], 2D;\n"
     5150    "TEX R1, R1, texture[2], 2D;\n"
     5151    "MUL R3.xyz, R1.w, R0;\n"
     5152    "MUL R2.xyz, R1, R0.w;\n"
    52045153    "MIN R2.xyz, R2, R3;\n"
    5205     "ADD R2.w, -R1, c[8].x;\n"
    5206     "MAD R0.xyz, R0, R2.w, R2;\n"
    5207     "ADD R2.x, -R0.w, c[8];\n"
    5208     "MAD R2.xyz, R1, R2.x, R0;\n"
    5209     "ADD R0.z, R0.w, R1.w;\n"
    5210     "MAD R2.w, -R0, R1, R0.z;\n"
    5211     "ADD R0.xy, fragment.position, c[0];\n"
    5212     "MUL R0.xy, R0, c[1];\n"
    5213     "TEX R0, R0, texture[1], 2D;\n"
    5214     "ADD R2, R2, -R1;\n"
    5215     "DP4 R0.x, R0, c[2];\n"
    5216     "MAD result.color, R0.x, R2, R1;\n"
     5154    "ADD R2.w, -R0, c[8].x;\n"
     5155    "MAD R1.xyz, R1, R2.w, R2;\n"
     5156    "ADD R2.x, -R1.w, c[8];\n"
     5157    "MAD R2.xyz, R0, R2.x, R1;\n"
     5158    "ADD R1.z, R1.w, R0.w;\n"
     5159    "MAD R2.w, -R1, R0, R1.z;\n"
     5160    "ADD R1.xy, fragment.position, c[6];\n"
     5161    "MUL R1.xy, R1, c[4];\n"
     5162    "TEX R1, R1, texture[1], 2D;\n"
     5163    "ADD R2, R2, -R0;\n"
     5164    "DP4 R1.x, R1, c[7];\n"
     5165    "MAD result.color, R1.x, R2, R0;\n"
    52175166    "END\n"
    52185167    ;
     
    52265175    "TEMP R2;\n"
    52275176    "TEMP R3;\n"
    5228     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5229     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5230     "ADD R0.xyz, R0, c[5];\n"
    5231     "RCP R0.z, R0.z;\n"
    5232     "MUL R0.xy, R0, R0.z;\n"
    5233     "MUL R0.xy, R0, c[6];\n"
    5234     "MOV R0.y, -R0;\n"
    5235     "MUL R1.xy, fragment.position, c[7];\n"
    5236     "TEX R1, R1, texture[0], 2D;\n"
    5237     "TEX R0, R0, texture[2], 2D;\n"
    5238     "MUL R3.xyz, R1, R0.w;\n"
    5239     "MUL R2.xyz, R0, R1.w;\n"
     5177    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5178    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5179    "ADD R0.xyz, R0, c[3];\n"
     5180    "RCP R0.z, R0.z;\n"
     5181    "MUL R0.zw, R0.xyxy, R0.z;\n"
     5182    "MUL R1.xy, R0.zwzw, c[0];\n"
     5183    "MUL R0.xy, fragment.position, c[5];\n"
     5184    "TEX R0, R0, texture[0], 2D;\n"
     5185    "TEX R1, R1, texture[2], 2D;\n"
     5186    "MUL R3.xyz, R1.w, R0;\n"
     5187    "MUL R2.xyz, R1, R0.w;\n"
    52405188    "MAX R2.xyz, R2, R3;\n"
    5241     "ADD R2.w, -R1, c[8].x;\n"
    5242     "MAD R0.xyz, R0, R2.w, R2;\n"
    5243     "ADD R2.x, -R0.w, c[8];\n"
    5244     "MAD R2.xyz, R1, R2.x, R0;\n"
    5245     "ADD R0.z, R0.w, R1.w;\n"
    5246     "MAD R2.w, -R0, R1, R0.z;\n"
    5247     "ADD R0.xy, fragment.position, c[0];\n"
    5248     "MUL R0.xy, R0, c[1];\n"
    5249     "TEX R0, R0, texture[1], 2D;\n"
    5250     "ADD R2, R2, -R1;\n"
    5251     "DP4 R0.x, R0, c[2];\n"
    5252     "MAD result.color, R0.x, R2, R1;\n"
     5189    "ADD R2.w, -R0, c[8].x;\n"
     5190    "MAD R1.xyz, R1, R2.w, R2;\n"
     5191    "ADD R2.x, -R1.w, c[8];\n"
     5192    "MAD R2.xyz, R0, R2.x, R1;\n"
     5193    "ADD R1.z, R1.w, R0.w;\n"
     5194    "MAD R2.w, -R1, R0, R1.z;\n"
     5195    "ADD R1.xy, fragment.position, c[6];\n"
     5196    "MUL R1.xy, R1, c[4];\n"
     5197    "TEX R1, R1, texture[1], 2D;\n"
     5198    "ADD R2, R2, -R0;\n"
     5199    "DP4 R1.x, R1, c[7];\n"
     5200    "MAD result.color, R1.x, R2, R0;\n"
    52535201    "END\n"
    52545202    ;
     
    52575205    "!!ARBfp1.0\n"
    52585206    "PARAM c[9] = { program.local[0..7],\n"
    5259     "           { 1, 1e-06 } };\n"
     5207    "           { 1, 1e-006 } };\n"
    52605208    "TEMP R0;\n"
    52615209    "TEMP R1;\n"
     
    52635211    "TEMP R3;\n"
    52645212    "TEMP R4;\n"
    5265     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5266     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5267     "ADD R0.xyz, R0, c[5];\n"
    5268     "RCP R0.z, R0.z;\n"
    5269     "MUL R0.xy, R0, R0.z;\n"
    5270     "MUL R0.xy, R0, c[6];\n"
    5271     "MOV R0.y, -R0;\n"
     5213    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5214    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5215    "ADD R0.xyz, R0, c[3];\n"
     5216    "RCP R0.z, R0.z;\n"
     5217    "MUL R0.xy, R0, R0.z;\n"
     5218    "MUL R0.xy, R0, c[0];\n"
    52725219    "TEX R0, R0, texture[2], 2D;\n"
    52735220    "MAX R1.x, R0.w, c[8].y;\n"
    52745221    "RCP R1.x, R1.x;\n"
    5275     "MAD R1.xyz, -R0, R1.x, c[8].x;\n"
    5276     "MAX R2.xyz, R1, c[8].y;\n"
    5277     "MUL R1.xy, fragment.position, c[7];\n"
     5222    "MAD R2.xyz, -R0, R1.x, c[8].x;\n"
     5223    "MAX R2.xyz, R2, c[8].y;\n"
     5224    "MUL R1.xy, fragment.position, c[5];\n"
    52785225    "TEX R1, R1, texture[0], 2D;\n"
    52795226    "ADD R2.w, -R0, c[8].x;\n"
     
    52815228    "ADD R2.w, -R1, c[8].x;\n"
    52825229    "MAD R4.xyz, R0, R2.w, R3;\n"
    5283     "MUL R3.xyz, R1, R0.w;\n"
     5230    "MUL R3.xyz, R0.w, R1;\n"
    52845231    "MUL R2.w, R0, R1;\n"
    52855232    "MAD R0.xyz, R0, R1.w, R3;\n"
     
    52945241    "ADD R0.z, R0.w, R1.w;\n"
    52955242    "MAD R2.w, -R0, R1, R0.z;\n"
    5296     "ADD R0.xy, fragment.position, c[0];\n"
    5297     "MUL R0.xy, R0, c[1];\n"
     5243    "ADD R0.xy, fragment.position, c[6];\n"
     5244    "MUL R0.xy, R0, c[4];\n"
    52985245    "TEX R0, R0, texture[1], 2D;\n"
    52995246    "ADD R2, R2, -R1;\n"
    5300     "DP4 R0.x, R0, c[2];\n"
     5247    "DP4 R0.x, R0, c[7];\n"
    53015248    "MAD result.color, R0.x, R2, R1;\n"
    53025249    "END\n"
     
    53065253    "!!ARBfp1.0\n"
    53075254    "PARAM c[9] = { program.local[0..7],\n"
    5308     "           { 1, 9.9999997e-06 } };\n"
     5255    "           { 1, 9.9999997e-006 } };\n"
    53095256    "TEMP R0;\n"
    53105257    "TEMP R1;\n"
     
    53135260    "TEMP R4;\n"
    53145261    "TEMP R5;\n"
    5315     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5316     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5317     "ADD R0.xyz, R0, c[5];\n"
    5318     "RCP R0.z, R0.z;\n"
    5319     "MUL R0.xy, R0, R0.z;\n"
    5320     "MUL R0.xy, R0, c[6];\n"
    5321     "MOV R0.y, -R0;\n"
     5262    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5263    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5264    "ADD R0.xyz, R0, c[3];\n"
     5265    "RCP R0.z, R0.z;\n"
     5266    "MUL R0.xy, R0, R0.z;\n"
     5267    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     5268    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5269    "MUL R0.xy, R0, c[0];\n"
    53225270    "TEX R0, R0, texture[2], 2D;\n"
    5323     "MUL R1.xy, fragment.position, c[7];\n"
    5324     "TEX R1, R1, texture[0], 2D;\n"
    5325     "MUL R2.xyz, R1, R0.w;\n"
     5271    "MUL R2.xyz, R0.w, R1;\n"
    53265272    "MAD R3.xyz, R0, R1.w, R2;\n"
    53275273    "MAD R2.xyz, -R0.w, R1.w, R3;\n"
     
    53385284    "MAD R0.xyz, R0, R2.w, R4;\n"
    53395285    "MUL R2.w, R0, R1;\n"
    5340     "ADD R3.w, -R0, c[8].x;\n"
    53415286    "MAD R2.xyz, R1, R3.w, R2;\n"
    53425287    "ADD R2.xyz, R2, -R0;\n"
     
    53455290    "ADD R0.z, R0.w, R1.w;\n"
    53465291    "MAD R2.w, -R0, R1, R0.z;\n"
    5347     "ADD R0.xy, fragment.position, c[0];\n"
    5348     "MUL R0.xy, R0, c[1];\n"
     5292    "ADD R0.xy, fragment.position, c[6];\n"
     5293    "MUL R0.xy, R0, c[4];\n"
    53495294    "TEX R0, R0, texture[1], 2D;\n"
    53505295    "ADD R2, R2, -R1;\n"
    5351     "DP4 R0.x, R0, c[2];\n"
     5296    "DP4 R0.x, R0, c[7];\n"
    53525297    "MAD result.color, R0.x, R2, R1;\n"
    53535298    "END\n"
     
    53635308    "TEMP R3;\n"
    53645309    "TEMP R4;\n"
    5365     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5366     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5367     "ADD R0.xyz, R0, c[5];\n"
    5368     "RCP R0.z, R0.z;\n"
    5369     "MUL R0.xy, R0, R0.z;\n"
    5370     "MUL R0.xy, R0, c[6];\n"
    5371     "MOV R0.y, -R0;\n"
     5310    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5311    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5312    "ADD R0.xyz, R0, c[3];\n"
     5313    "RCP R0.z, R0.z;\n"
     5314    "MUL R0.xy, R0, R0.z;\n"
     5315    "MUL R0.xy, R0, c[0];\n"
    53725316    "TEX R0, R0, texture[2], 2D;\n"
    5373     "MUL R1.xy, fragment.position, c[7];\n"
     5317    "MUL R1.xy, fragment.position, c[5];\n"
    53745318    "TEX R1, R1, texture[0], 2D;\n"
    53755319    "ADD R2.w, -R1, c[8].y;\n"
     
    53925336    "ADD R0.z, R0.w, R1.w;\n"
    53935337    "MAD R2.w, -R0, R1, R0.z;\n"
    5394     "ADD R0.xy, fragment.position, c[0];\n"
    5395     "MUL R0.xy, R0, c[1];\n"
     5338    "ADD R0.xy, fragment.position, c[6];\n"
     5339    "MUL R0.xy, R0, c[4];\n"
    53965340    "TEX R0, R0, texture[1], 2D;\n"
    53975341    "ADD R2, R2, -R1;\n"
    5398     "DP4 R0.x, R0, c[2];\n"
     5342    "DP4 R0.x, R0, c[7];\n"
    53995343    "MAD result.color, R0.x, R2, R1;\n"
    54005344    "END\n"
     
    54045348    "!!ARBfp1.0\n"
    54055349    "PARAM c[10] = { program.local[0..7],\n"
    5406     "           { 1, 9.9999997e-06, 2, 8 },\n"
    5407     "           { 3 } };\n"
     5350    "           { 1, 2, 9.9999997e-006, 4 },\n"
     5351    "           { 16, 12, 3 } };\n"
    54085352    "TEMP R0;\n"
    54095353    "TEMP R1;\n"
     
    54135357    "TEMP R5;\n"
    54145358    "TEMP R6;\n"
    5415     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5416     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5417     "ADD R0.xyz, R0, c[5];\n"
    5418     "RCP R0.z, R0.z;\n"
    5419     "MUL R0.xy, R0, R0.z;\n"
    5420     "MUL R0.xy, R0, c[6];\n"
    5421     "MUL R1.xy, fragment.position, c[7];\n"
     5359    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5360    "MUL R1.xy, fragment.position, c[5];\n"
    54225361    "TEX R1, R1, texture[0], 2D;\n"
    5423     "MAX R0.z, R1.w, c[8].y;\n"
    5424     "RCP R2.w, R0.z;\n"
    5425     "MUL R2.xyz, R1, R2.w;\n"
    5426     "MUL R6.xyz, -R2, c[8].w;\n"
    5427     "MAD R3.xyz, -R1, R2.w, c[8].x;\n"
    5428     "MOV R0.y, -R0;\n"
     5362    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5363    "ADD R0.xyz, R0, c[3];\n"
     5364    "RCP R0.z, R0.z;\n"
     5365    "MUL R0.xy, R0, R0.z;\n"
     5366    "MAX R0.w, R1, c[8].z;\n"
     5367    "RCP R0.w, R0.w;\n"
     5368    "MUL R3.xyz, R1, R0.w;\n"
     5369    "MAD R2.xyz, R3, c[9].x, -c[9].y;\n"
     5370    "MUL R0.xy, R0, c[0];\n"
    54295371    "TEX R0, R0, texture[2], 2D;\n"
    5430     "MAD R4.xyz, R0, c[8].z, -R0.w;\n"
    5431     "MUL R5.xyz, R3, R4;\n"
    5432     "MAD R3.xyz, -R3, R4, R0.w;\n"
    5433     "ADD R6.xyz, R6, c[9].x;\n"
    5434     "RSQ R2.x, R2.x;\n"
    5435     "RSQ R2.z, R2.z;\n"
    5436     "RSQ R2.y, R2.y;\n"
    5437     "MAD R5.xyz, -R5, R6, R0.w;\n"
    5438     "MUL R3.xyz, R1, R3;\n"
     5372    "MAD R4.xyz, R3, R2, c[9].z;\n"
     5373    "MAD R2.xyz, R0, c[8].y, -R0.w;\n"
     5374    "MUL R5.xyz, R1.w, R2;\n"
     5375    "MUL R6.xyz, R5, R4;\n"
     5376    "RSQ R2.w, R3.x;\n"
     5377    "RCP R4.x, R2.w;\n"
     5378    "RSQ R2.w, R3.y;\n"
     5379    "RSQ R3.w, R3.z;\n"
     5380    "RCP R4.y, R2.w;\n"
     5381    "RCP R4.z, R3.w;\n"
     5382    "ADD R4.xyz, -R3, R4;\n"
     5383    "MUL R6.xyz, R3, R6;\n"
     5384    "MUL R4.xyz, R5, R4;\n"
     5385    "ADD R3.xyz, -R3, c[8].x;\n"
     5386    "MAD R2.xyz, R2, R3, R0.w;\n"
     5387    "MUL R3.xyz, R0, c[8].y;\n"
     5388    "MAD R5.xyz, R0.w, R1, R6;\n"
     5389    "MAD R4.xyz, R0.w, R1, R4;\n"
     5390    "ADD R6.xyz, R4, -R5;\n"
     5391    "MUL R4.xyz, R1, c[8].w;\n"
     5392    "SGE R4.xyz, R4, R1.w;\n"
     5393    "MAD R4.xyz, R4, R6, R5;\n"
     5394    "MAD R4.xyz, -R1, R2, R4;\n"
     5395    "SGE R3.xyz, R3, R0.w;\n"
     5396    "MUL R2.xyz, R1, R2;\n"
    54395397    "ADD R2.w, -R1, c[8].x;\n"
    5440     "RCP R2.x, R2.x;\n"
    5441     "RCP R2.z, R2.z;\n"
    5442     "RCP R2.y, R2.y;\n"
    5443     "MAD R2.xyz, R2, R1.w, -R1;\n"
    5444     "MUL R6.xyz, R2, R4;\n"
    5445     "MUL R2.xyz, R1, R5;\n"
    5446     "MAD R6.xyz, R1, R0.w, R6;\n"
    5447     "MUL R4.xyz, R0, c[8].z;\n"
    5448     "MUL R5.xyz, R1, c[8].w;\n"
    5449     "ADD R6.xyz, R6, -R2;\n"
    5450     "SGE R5.xyz, R5, R1.w;\n"
    5451     "MUL R5.xyz, R5, R6;\n"
    5452     "ADD R2.xyz, R2, R5;\n"
    5453     "SGE R4.xyz, R4, R0.w;\n"
    5454     "ADD R2.xyz, R2, -R3;\n"
    5455     "MUL R2.xyz, R4, R2;\n"
    5456     "ADD R2.xyz, R3, R2;\n"
    5457     "MAD R0.xyz, R0, R2.w, R2;\n"
    5458     "ADD R2.x, -R0.w, c[8];\n"
    5459     "MAD R2.xyz, R1, R2.x, R0;\n"
     5398    "MAD R2.xyz, R3, R4, R2;\n"
     5399    "MAD R2.xyz, R0, R2.w, R2;\n"
     5400    "ADD R0.x, -R0.w, c[8];\n"
     5401    "MAD R2.xyz, R1, R0.x, R2;\n"
    54605402    "ADD R0.z, R0.w, R1.w;\n"
    54615403    "MAD R2.w, -R0, R1, R0.z;\n"
    5462     "ADD R0.xy, fragment.position, c[0];\n"
    5463     "MUL R0.xy, R0, c[1];\n"
     5404    "ADD R0.xy, fragment.position, c[6];\n"
     5405    "MUL R0.xy, R0, c[4];\n"
    54645406    "TEX R0, R0, texture[1], 2D;\n"
    54655407    "ADD R2, R2, -R1;\n"
    5466     "DP4 R0.x, R0, c[2];\n"
     5408    "DP4 R0.x, R0, c[7];\n"
    54675409    "MAD result.color, R0.x, R2, R1;\n"
    54685410    "END\n"
     
    54775419    "TEMP R2;\n"
    54785420    "TEMP R3;\n"
    5479     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5480     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5481     "ADD R0.xyz, R0, c[5];\n"
    5482     "RCP R0.z, R0.z;\n"
    5483     "MUL R0.xy, R0, R0.z;\n"
    5484     "MUL R0.xy, R0, c[6];\n"
    5485     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    5486     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5487     "MOV R0.y, -R0;\n"
    5488     "TEX R0, R0, texture[2], 2D;\n"
    5489     "ADD R3.xyz, R0, R1;\n"
    5490     "MUL R2.xyz, R1, R0.w;\n"
    5491     "MUL R0.xyz, R0, R1.w;\n"
    5492     "MIN R0.xyz, R0, R2;\n"
    5493     "MAD R2.xyz, -R0, c[8].x, R3;\n"
    5494     "ADD R0.z, R0.w, R1.w;\n"
    5495     "MAD R2.w, -R0, R1, R0.z;\n"
    5496     "ADD R0.xy, fragment.position, c[0];\n"
    5497     "MUL R0.xy, R0, c[1];\n"
     5421    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5422    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5423    "ADD R0.xyz, R0, c[3];\n"
     5424    "RCP R0.z, R0.z;\n"
     5425    "MUL R0.zw, R0.xyxy, R0.z;\n"
     5426    "MUL R1.xy, R0.zwzw, c[0];\n"
     5427    "MUL R0.xy, fragment.position, c[5];\n"
     5428    "TEX R0, R0, texture[0], 2D;\n"
     5429    "TEX R1, R1, texture[2], 2D;\n"
     5430    "ADD R2.xyz, R1, R0;\n"
     5431    "MUL R3.xyz, R1.w, R0;\n"
     5432    "MUL R1.xyz, R1, R0.w;\n"
     5433    "MIN R1.xyz, R1, R3;\n"
     5434    "MAD R2.xyz, -R1, c[8].x, R2;\n"
     5435    "ADD R1.z, R1.w, R0.w;\n"
     5436    "MAD R2.w, -R1, R0, R1.z;\n"
     5437    "ADD R1.xy, fragment.position, c[6];\n"
     5438    "MUL R1.xy, R1, c[4];\n"
     5439    "TEX R1, R1, texture[1], 2D;\n"
     5440    "ADD R2, R2, -R0;\n"
     5441    "DP4 R1.x, R1, c[7];\n"
     5442    "MAD result.color, R1.x, R2, R0;\n"
     5443    "END\n"
     5444    ;
     5445
     5446static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION =
     5447    "!!ARBfp1.0\n"
     5448    "PARAM c[9] = { program.local[0..7],\n"
     5449    "           { 2, 1 } };\n"
     5450    "TEMP R0;\n"
     5451    "TEMP R1;\n"
     5452    "TEMP R2;\n"
     5453    "TEMP R3;\n"
     5454    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5455    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5456    "ADD R0.xyz, R0, c[3];\n"
     5457    "RCP R0.z, R0.z;\n"
     5458    "MUL R0.zw, R0.xyxy, R0.z;\n"
     5459    "MUL R1.xy, R0.zwzw, c[0];\n"
     5460    "MUL R0.xy, fragment.position, c[5];\n"
     5461    "TEX R0, R0, texture[0], 2D;\n"
     5462    "TEX R1, R1, texture[2], 2D;\n"
     5463    "MUL R2.xyz, R1.w, R0;\n"
     5464    "MAD R3.xyz, R1, R0.w, R2;\n"
     5465    "MUL R2.xyz, R1, R0;\n"
     5466    "MAD R2.xyz, -R2, c[8].x, R3;\n"
     5467    "ADD R2.w, -R0, c[8].y;\n"
     5468    "MAD R1.xyz, R1, R2.w, R2;\n"
     5469    "ADD R2.x, -R1.w, c[8].y;\n"
     5470    "MAD R2.xyz, R0, R2.x, R1;\n"
     5471    "ADD R1.z, R1.w, R0.w;\n"
     5472    "MAD R2.w, -R1, R0, R1.z;\n"
     5473    "ADD R1.xy, fragment.position, c[6];\n"
     5474    "MUL R1.xy, R1, c[4];\n"
     5475    "TEX R1, R1, texture[1], 2D;\n"
     5476    "ADD R2, R2, -R0;\n"
     5477    "DP4 R1.x, R1, c[7];\n"
     5478    "MAD result.color, R1.x, R2, R0;\n"
     5479    "END\n"
     5480    ;
     5481
     5482static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
     5483    "!!ARBfp1.0\n"
     5484    "PARAM c[8] = { program.local[0..6],\n"
     5485    "           { 1 } };\n"
     5486    "TEMP R0;\n"
     5487    "TEMP R1;\n"
     5488    "TEMP R2;\n"
     5489    "TEMP R3;\n"
     5490    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5491    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5492    "ADD R0.xyz, R0, c[3];\n"
     5493    "RCP R0.z, R0.z;\n"
     5494    "MUL R0.xy, R0, R0.z;\n"
     5495    "MUL R1.xy, fragment.position, c[6];\n"
     5496    "TEX R1, R1, texture[0], 2D;\n"
     5497    "MUL R2.xyz, R1, c[4].y;\n"
     5498    "MUL R0.xy, R0, c[0];\n"
    54985499    "TEX R0, R0, texture[1], 2D;\n"
    5499     "ADD R2, R2, -R1;\n"
    5500     "DP4 R0.x, R0, c[2];\n"
    5501     "MAD result.color, R0.x, R2, R1;\n"
    5502     "END\n"
    5503     ;
    5504 
    5505 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_EXCLUSION =
    5506     "!!ARBfp1.0\n"
    5507     "PARAM c[9] = { program.local[0..7],\n"
    5508     "           { 1, 2 } };\n"
    5509     "TEMP R0;\n"
    5510     "TEMP R1;\n"
    5511     "TEMP R2;\n"
    5512     "TEMP R3;\n"
    5513     "MUL R0.xyz, fragment.position.y, c[4];\n"
    5514     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    5515     "ADD R0.xyz, R0, c[5];\n"
    5516     "RCP R0.z, R0.z;\n"
    5517     "MUL R0.xy, R0, R0.z;\n"
    5518     "MUL R0.xy, R0, c[6];\n"
    5519     "MOV R0.y, -R0;\n"
    5520     "MUL R1.xy, fragment.position, c[7];\n"
    5521     "TEX R1, R1, texture[0], 2D;\n"
    5522     "TEX R0, R0, texture[2], 2D;\n"
    5523     "MUL R2.xyz, R1, R0.w;\n"
    5524     "MAD R3.xyz, R0, R1.w, R2;\n"
    5525     "MUL R2.xyz, R0, R1;\n"
    5526     "MAD R2.xyz, -R2, c[8].y, R3;\n"
    5527     "ADD R2.w, -R1, c[8].x;\n"
    5528     "MAD R0.xyz, R0, R2.w, R2;\n"
    5529     "ADD R2.x, -R0.w, c[8];\n"
    5530     "MAD R2.xyz, R1, R2.x, R0;\n"
    5531     "ADD R0.z, R0.w, R1.w;\n"
    5532     "MAD R2.w, -R0, R1, R0.z;\n"
    5533     "ADD R0.xy, fragment.position, c[0];\n"
    5534     "MUL R0.xy, R0, c[1];\n"
    5535     "TEX R0, R0, texture[1], 2D;\n"
    5536     "ADD R2, R2, -R1;\n"
    5537     "DP4 R0.x, R0, c[2];\n"
    5538     "MAD result.color, R0.x, R2, R1;\n"
    5539     "END\n"
    5540     ;
    5541 
    5542 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_TEXTURE_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    5543     "!!ARBfp1.0\n"
    5544     "PARAM c[8] = { program.local[0..4],\n"
    5545     "           { 1 },\n"
    5546     "           program.local[6..7] };\n"
    5547     "TEMP R0;\n"
    5548     "TEMP R1;\n"
    5549     "TEMP R2;\n"
    5550     "TEMP R3;\n"
    5551     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5552     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5553     "ADD R0.xyz, R0, c[2];\n"
    5554     "RCP R0.z, R0.z;\n"
    5555     "MUL R0.xy, R0, R0.z;\n"
    5556     "MUL R0.xy, R0, c[3];\n"
    5557     "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    5558     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5559     "MUL R2.xyz, R1, c[7].y;\n"
    5560     "MOV R0.y, -R0;\n"
    5561     "TEX R0, R0, texture[1], 2D;\n"
    5562     "MUL R3.xyz, R2, R0.w;\n"
    5563     "MUL R2.xyz, R0, c[7].x;\n"
    5564     "MAD R2.xyz, R2, R1.w, R3;\n"
    5565     "MUL R0.xyz, R0, c[6].y;\n"
    5566     "ADD R2.w, -R1, c[5].x;\n"
    5567     "MAD R0.xyz, R0, R2.w, R2;\n"
    5568     "ADD R2.x, -R0.w, c[5];\n"
    5569     "MUL R1.xyz, R1, c[6].z;\n"
    5570     "MAD result.color.xyz, R1, R2.x, R0;\n"
    5571     "ADD R0.y, -R1.w, c[5].x;\n"
     5500    "MUL R3.xyz, R0.w, R2;\n"
     5501    "MUL R2.xyz, R0, c[4].x;\n"
     5502    "MAD R2.xyz, R1.w, R2, R3;\n"
     5503    "ADD R2.w, -R1, c[7].x;\n"
     5504    "MUL R0.xyz, R0, c[5].y;\n"
     5505    "MAD R0.xyz, R2.w, R0, R2;\n"
     5506    "ADD R2.x, -R0.w, c[7];\n"
     5507    "MUL R1.xyz, R1, c[5].z;\n"
     5508    "MAD result.color.xyz, R2.x, R1, R0;\n"
    55725509    "MUL R0.x, R0.w, R1.w;\n"
    55735510    "MUL R0.z, R1.w, R2.x;\n"
    5574     "MUL R0.y, R0.w, R0;\n"
    5575     "DP3 result.color.w, R0, c[6];\n"
     5511    "MUL R0.y, R0.w, R2.w;\n"
     5512    "DP3 result.color.w, R0, c[5];\n"
    55765513    "END\n"
    55775514    ;
     
    55845521    "TEMP R1;\n"
    55855522    "TEMP R2;\n"
    5586     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5587     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5588     "ADD R0.xyz, R0, c[2];\n"
    5589     "RCP R1.x, R0.z;\n"
    5590     "MUL R0.xy, R0, R1.x;\n"
    5591     "MUL R0.xy, R0, c[3];\n"
    5592     "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    5593     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5594     "MOV R0.y, -R0;\n"
     5523    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5524    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5525    "ADD R0.xyz, R0, c[3];\n"
     5526    "RCP R0.z, R0.z;\n"
     5527    "MUL R0.xy, R0, R0.z;\n"
     5528    "MUL R1.xy, fragment.position, c[4];\n"
     5529    "TEX R1, R1, texture[0], 2D;\n"
     5530    "MUL R0.xy, R0, c[0];\n"
    55955531    "TEX R0, R0, texture[1], 2D;\n"
    55965532    "ADD R2.x, -R1.w, c[5];\n"
     
    56105546    "TEMP R1;\n"
    56115547    "TEMP R2;\n"
    5612     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5613     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5614     "ADD R0.xyz, R0, c[2];\n"
    5615     "RCP R0.z, R0.z;\n"
    5616     "MUL R0.xy, R0, R0.z;\n"
    5617     "MUL R0.xy, R0, c[3];\n"
     5548    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5549    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5550    "ADD R0.xyz, R0, c[3];\n"
     5551    "RCP R0.z, R0.z;\n"
     5552    "MUL R0.xy, R0, R0.z;\n"
    56185553    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
    56195554    "TEX R1, R0.zwzw, texture[0], 2D;\n"
    5620     "MOV R0.y, -R0;\n"
     5555    "MUL R0.xy, R0, c[0];\n"
    56215556    "TEX R0, R0, texture[1], 2D;\n"
    56225557    "ADD R2, R0, R1;\n"
     
    56335568    "TEMP R2;\n"
    56345569    "TEMP R3;\n"
    5635     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5636     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5637     "ADD R0.xyz, R0, c[2];\n"
    5638     "RCP R0.z, R0.z;\n"
    5639     "MUL R0.xy, R0, R0.z;\n"
    5640     "MUL R0.xy, R0, c[3];\n"
    5641     "MOV R0.y, -R0;\n"
     5570    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5571    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5572    "ADD R0.xyz, R0, c[3];\n"
     5573    "RCP R0.z, R0.z;\n"
     5574    "MUL R0.xy, R0, R0.z;\n"
     5575    "MUL R0.xy, R0, c[0];\n"
    56425576    "TEX R0, R0, texture[1], 2D;\n"
    56435577    "MUL R1.xy, fragment.position, c[4];\n"
     
    56735607    "TEMP R2;\n"
    56745608    "TEMP R3;\n"
    5675     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5676     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5677     "ADD R0.xyz, R0, c[2];\n"
    5678     "RCP R0.z, R0.z;\n"
    5679     "MUL R0.xy, R0, R0.z;\n"
    5680     "MUL R0.xy, R0, c[3];\n"
    5681     "MOV R0.y, -R0;\n"
    5682     "MUL R1.xy, fragment.position, c[4];\n"
    5683     "TEX R1, R1, texture[0], 2D;\n"
     5609    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5610    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5611    "ADD R0.xyz, R0, c[3];\n"
     5612    "RCP R0.z, R0.z;\n"
     5613    "MUL R0.xy, R0, R0.z;\n"
     5614    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     5615    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5616    "MUL R0.xy, R0, c[0];\n"
    56845617    "TEX R0, R0, texture[1], 2D;\n"
    56855618    "MUL R2.xyz, R0, R1.w;\n"
    5686     "MUL R3.xyz, R1, R0.w;\n"
     5619    "MUL R3.xyz, R0.w, R1;\n"
    56875620    "MIN R2.xyz, R2, R3;\n"
    56885621    "ADD R2.w, -R1, c[5].x;\n"
     
    57035636    "TEMP R2;\n"
    57045637    "TEMP R3;\n"
    5705     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5706     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5707     "ADD R0.xyz, R0, c[2];\n"
    5708     "RCP R0.z, R0.z;\n"
    5709     "MUL R0.xy, R0, R0.z;\n"
    5710     "MUL R0.xy, R0, c[3];\n"
    5711     "MOV R0.y, -R0;\n"
    5712     "MUL R1.xy, fragment.position, c[4];\n"
    5713     "TEX R1, R1, texture[0], 2D;\n"
     5638    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5639    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5640    "ADD R0.xyz, R0, c[3];\n"
     5641    "RCP R0.z, R0.z;\n"
     5642    "MUL R0.xy, R0, R0.z;\n"
     5643    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     5644    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5645    "MUL R0.xy, R0, c[0];\n"
    57145646    "TEX R0, R0, texture[1], 2D;\n"
    57155647    "MUL R2.xyz, R0, R1.w;\n"
    5716     "MUL R3.xyz, R1, R0.w;\n"
     5648    "MUL R3.xyz, R0.w, R1;\n"
    57175649    "MAX R2.xyz, R2, R3;\n"
    57185650    "ADD R2.w, -R1, c[5].x;\n"
     
    57285660    "!!ARBfp1.0\n"
    57295661    "PARAM c[6] = { program.local[0..4],\n"
    5730     "           { 1, 1e-06 } };\n"
    5731     "TEMP R0;\n"
    5732     "TEMP R1;\n"
    5733     "TEMP R2;\n"
    5734     "TEMP R3;\n"
    5735     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5736     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5737     "ADD R0.xyz, R0, c[2];\n"
    5738     "RCP R0.z, R0.z;\n"
    5739     "MUL R0.xy, R0, R0.z;\n"
    5740     "MUL R0.xy, R0, c[3];\n"
    5741     "MOV R0.y, -R0;\n"
     5662    "           { 1, 1e-006 } };\n"
     5663    "TEMP R0;\n"
     5664    "TEMP R1;\n"
     5665    "TEMP R2;\n"
     5666    "TEMP R3;\n"
     5667    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5668    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5669    "ADD R0.xyz, R0, c[3];\n"
     5670    "RCP R0.z, R0.z;\n"
     5671    "MUL R0.xy, R0, R0.z;\n"
     5672    "MUL R0.xy, R0, c[0];\n"
    57425673    "TEX R0, R0, texture[1], 2D;\n"
    57435674    "MAX R1.x, R0.w, c[5].y;\n"
    57445675    "RCP R1.x, R1.x;\n"
    5745     "MAD R1.xyz, -R0, R1.x, c[5].x;\n"
    5746     "MAX R2.xyz, R1, c[5].y;\n"
     5676    "MAD R3.xyz, -R0, R1.x, c[5].x;\n"
     5677    "MAX R3.xyz, R3, c[5].y;\n"
    57475678    "MUL R1.xy, fragment.position, c[4];\n"
    57485679    "TEX R1, R1, texture[0], 2D;\n"
    5749     "ADD R2.w, -R0, c[5].x;\n"
    5750     "MUL R3.xyz, R1, R2.w;\n"
     5680    "ADD R2.x, -R0.w, c[5];\n"
     5681    "MUL R2.xyz, R1, R2.x;\n"
    57515682    "ADD R2.w, -R1, c[5].x;\n"
    5752     "MAD R3.xyz, R0, R2.w, R3;\n"
    5753     "MUL R1.xyz, R1, R0.w;\n"
     5683    "MAD R2.xyz, R0, R2.w, R2;\n"
     5684    "MUL R1.xyz, R0.w, R1;\n"
    57545685    "MAD R0.xyz, R0, R1.w, R1;\n"
    57555686    "MUL R2.w, R0, R1;\n"
    5756     "RCP R2.x, R2.x;\n"
    5757     "RCP R2.y, R2.y;\n"
    5758     "RCP R2.z, R2.z;\n"
    5759     "MAD R2.xyz, R1, R2, R3;\n"
    5760     "MAD R3.xyz, R0.w, R1.w, R3;\n"
     5687    "RCP R3.x, R3.x;\n"
     5688    "RCP R3.y, R3.y;\n"
     5689    "RCP R3.z, R3.z;\n"
     5690    "MAD R3.xyz, R1, R3, R2;\n"
     5691    "MAD R2.xyz, R0.w, R1.w, R2;\n"
    57615692    "ADD R1.x, R0.w, R1.w;\n"
    5762     "ADD R3.xyz, R3, -R2;\n"
     5693    "ADD R2.xyz, R2, -R3;\n"
    57635694    "SGE R0.xyz, R0, R2.w;\n"
    5764     "MAD result.color.xyz, R0, R3, R2;\n"
     5695    "MAD result.color.xyz, R0, R2, R3;\n"
    57655696    "MAD result.color.w, -R0, R1, R1.x;\n"
    57665697    "END\n"
     
    57705701    "!!ARBfp1.0\n"
    57715702    "PARAM c[6] = { program.local[0..4],\n"
    5772     "           { 1, 9.9999997e-06 } };\n"
     5703    "           { 1, 9.9999997e-006 } };\n"
    57735704    "TEMP R0;\n"
    57745705    "TEMP R1;\n"
     
    57775708    "TEMP R4;\n"
    57785709    "TEMP R5;\n"
    5779     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5780     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5781     "ADD R0.xyz, R0, c[2];\n"
    5782     "RCP R0.z, R0.z;\n"
    5783     "MUL R0.xy, R0, R0.z;\n"
    5784     "MUL R0.xy, R0, c[3];\n"
    5785     "MOV R0.y, -R0;\n"
     5710    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5711    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5712    "ADD R0.xyz, R0, c[3];\n"
     5713    "RCP R0.z, R0.z;\n"
     5714    "MUL R0.xy, R0, R0.z;\n"
     5715    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     5716    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5717    "MUL R0.xy, R0, c[0];\n"
    57865718    "TEX R0, R0, texture[1], 2D;\n"
    5787     "MUL R1.xy, fragment.position, c[4];\n"
    5788     "TEX R1, R1, texture[0], 2D;\n"
    5789     "MUL R2.xyz, R1, R0.w;\n"
     5719    "MUL R2.xyz, R0.w, R1;\n"
    57905720    "MAD R3.xyz, R0, R1.w, R2;\n"
    57915721    "ADD R2.w, -R1, c[5].x;\n"
     
    58005730    "MAD R2.xyz, R4, R2, R5;\n"
    58015731    "MUL R4.xyz, R1, R3.w;\n"
     5732    "MAD R1.xyz, R1, R3.w, R2;\n"
    58025733    "MAD R0.xyz, R0, R2.w, R4;\n"
    5803     "ADD R3.w, -R0, c[5].x;\n"
    5804     "MAD R1.xyz, R1, R3.w, R2;\n"
    58055734    "MUL R2.x, R0.w, R1.w;\n"
    58065735    "ADD R2.w, R0, R1;\n"
     
    58215750    "TEMP R3;\n"
    58225751    "TEMP R4;\n"
    5823     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5824     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5825     "ADD R0.xyz, R0, c[2];\n"
    5826     "RCP R0.z, R0.z;\n"
    5827     "MUL R0.xy, R0, R0.z;\n"
    5828     "MUL R0.xy, R0, c[3];\n"
    5829     "MOV R0.y, -R0;\n"
     5752    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5753    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5754    "ADD R0.xyz, R0, c[3];\n"
     5755    "RCP R0.z, R0.z;\n"
     5756    "MUL R0.xy, R0, R0.z;\n"
     5757    "MUL R0.xy, R0, c[0];\n"
    58305758    "TEX R0, R0, texture[1], 2D;\n"
    58315759    "MUL R1.xy, fragment.position, c[4];\n"
     
    58375765    "MUL R2.xyz, R2, c[5].x;\n"
    58385766    "MAD R2.xyz, R0.w, R1.w, -R2;\n"
     5767    "MAD R2.xyz, R0, R2.w, R2;\n"
    58395768    "MUL R4.xyz, R0, R2.w;\n"
    58405769    "MUL R3.xyz, R0, R1;\n"
    5841     "MAD R2.xyz, R0, R2.w, R2;\n"
     5770    "MUL R0.xyz, R0, c[5].x;\n"
    58425771    "ADD R2.w, -R0, c[5].y;\n"
    5843     "MUL R0.xyz, R0, c[5].x;\n"
    5844     "MAD R2.xyz, R1, R2.w, R2;\n"
    58455772    "MAD R3.xyz, R3, c[5].x, R4;\n"
    5846     "MAD R1.xyz, R1, R2.w, R3;\n"
    5847     "ADD R2.w, R0, R1;\n"
    5848     "ADD R2.xyz, R2, -R1;\n"
     5773    "MAD R3.xyz, R1, R2.w, R3;\n"
     5774    "MAD R1.xyz, R1, R2.w, R2;\n"
     5775    "ADD R2.x, R0.w, R1.w;\n"
     5776    "ADD R1.xyz, R1, -R3;\n"
    58495777    "SGE R0.xyz, R0, R0.w;\n"
    5850     "MAD result.color.xyz, R0, R2, R1;\n"
    5851     "MAD result.color.w, -R0, R1, R2;\n"
     5778    "MAD result.color.xyz, R0, R1, R3;\n"
     5779    "MAD result.color.w, -R0, R1, R2.x;\n"
    58525780    "END\n"
    58535781    ;
     
    58565784    "!!ARBfp1.0\n"
    58575785    "PARAM c[7] = { program.local[0..4],\n"
    5858     "           { 1, 9.9999997e-06, 2, 8 },\n"
    5859     "           { 3 } };\n"
     5786    "           { 1, 2, 9.9999997e-006, 4 },\n"
     5787    "           { 16, 12, 3 } };\n"
    58605788    "TEMP R0;\n"
    58615789    "TEMP R1;\n"
     
    58655793    "TEMP R5;\n"
    58665794    "TEMP R6;\n"
    5867     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5868     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5869     "ADD R0.xyz, R0, c[2];\n"
    5870     "RCP R0.z, R0.z;\n"
    5871     "MUL R0.xy, R0, R0.z;\n"
    5872     "MUL R0.xy, R0, c[3];\n"
     5795    "MUL R0.xyz, fragment.position.y, c[2];\n"
    58735796    "MUL R1.xy, fragment.position, c[4];\n"
    58745797    "TEX R1, R1, texture[0], 2D;\n"
    5875     "MAX R0.z, R1.w, c[5].y;\n"
    5876     "RCP R2.w, R0.z;\n"
    5877     "MUL R2.xyz, R1, R2.w;\n"
    5878     "MUL R6.xyz, -R2, c[5].w;\n"
    5879     "MAD R3.xyz, -R1, R2.w, c[5].x;\n"
    5880     "MOV R0.y, -R0;\n"
     5798    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5799    "ADD R0.xyz, R0, c[3];\n"
     5800    "RCP R0.z, R0.z;\n"
     5801    "MUL R0.xy, R0, R0.z;\n"
     5802    "MAX R0.w, R1, c[5].z;\n"
     5803    "RCP R0.w, R0.w;\n"
     5804    "MUL R3.xyz, R1, R0.w;\n"
     5805    "MAD R2.xyz, R3, c[6].x, -c[6].y;\n"
     5806    "MUL R0.xy, R0, c[0];\n"
    58815807    "TEX R0, R0, texture[1], 2D;\n"
    5882     "MAD R4.xyz, R0, c[5].z, -R0.w;\n"
    5883     "MUL R5.xyz, R3, R4;\n"
    5884     "MAD R3.xyz, -R3, R4, R0.w;\n"
    5885     "ADD R6.xyz, R6, c[6].x;\n"
    5886     "RSQ R2.x, R2.x;\n"
    5887     "RSQ R2.z, R2.z;\n"
    5888     "RSQ R2.y, R2.y;\n"
    5889     "MAD R5.xyz, -R5, R6, R0.w;\n"
    5890     "MUL R3.xyz, R1, R3;\n"
    5891     "RCP R2.x, R2.x;\n"
    5892     "RCP R2.z, R2.z;\n"
    5893     "RCP R2.y, R2.y;\n"
    5894     "MAD R2.xyz, R2, R1.w, -R1;\n"
    5895     "MUL R6.xyz, R2, R4;\n"
    5896     "MUL R2.xyz, R1, R5;\n"
    5897     "MUL R4.xyz, R0, c[5].z;\n"
    5898     "MAD R6.xyz, R1, R0.w, R6;\n"
    5899     "MUL R5.xyz, R1, c[5].w;\n"
    5900     "ADD R6.xyz, R6, -R2;\n"
    5901     "SGE R5.xyz, R5, R1.w;\n"
    5902     "MUL R5.xyz, R5, R6;\n"
    5903     "ADD R2.xyz, R2, R5;\n"
    5904     "ADD R2.xyz, R2, -R3;\n"
    5905     "SGE R4.xyz, R4, R0.w;\n"
    5906     "MUL R2.xyz, R4, R2;\n"
    5907     "ADD R2.xyz, R3, R2;\n"
     5808    "MAD R4.xyz, R3, R2, c[6].z;\n"
     5809    "MAD R2.xyz, R0, c[5].y, -R0.w;\n"
     5810    "MUL R5.xyz, R1.w, R2;\n"
     5811    "MUL R6.xyz, R5, R4;\n"
     5812    "RSQ R2.w, R3.x;\n"
     5813    "RCP R4.x, R2.w;\n"
     5814    "RSQ R2.w, R3.y;\n"
     5815    "RSQ R3.w, R3.z;\n"
     5816    "RCP R4.y, R2.w;\n"
     5817    "RCP R4.z, R3.w;\n"
     5818    "ADD R4.xyz, -R3, R4;\n"
     5819    "MUL R6.xyz, R3, R6;\n"
     5820    "MUL R4.xyz, R5, R4;\n"
     5821    "ADD R3.xyz, -R3, c[5].x;\n"
     5822    "MAD R2.xyz, R2, R3, R0.w;\n"
     5823    "MUL R3.xyz, R0, c[5].y;\n"
     5824    "MAD R5.xyz, R0.w, R1, R6;\n"
     5825    "MAD R4.xyz, R0.w, R1, R4;\n"
     5826    "ADD R6.xyz, R4, -R5;\n"
     5827    "MUL R4.xyz, R1, c[5].w;\n"
     5828    "SGE R4.xyz, R4, R1.w;\n"
     5829    "MAD R4.xyz, R4, R6, R5;\n"
     5830    "MAD R4.xyz, -R1, R2, R4;\n"
     5831    "MUL R2.xyz, R1, R2;\n"
     5832    "SGE R3.xyz, R3, R0.w;\n"
     5833    "MAD R2.xyz, R3, R4, R2;\n"
    59085834    "ADD R2.w, -R1, c[5].x;\n"
    5909     "MAD R0.xyz, R0, R2.w, R2;\n"
    5910     "ADD R2.x, R0.w, R1.w;\n"
    5911     "ADD R2.y, -R0.w, c[5].x;\n"
    5912     "MAD result.color.xyz, R1, R2.y, R0;\n"
    5913     "MAD result.color.w, -R0, R1, R2.x;\n"
     5835    "MAD R2.xyz, R0, R2.w, R2;\n"
     5836    "ADD R0.x, R0.w, R1.w;\n"
     5837    "ADD R0.y, -R0.w, c[5].x;\n"
     5838    "MAD result.color.xyz, R1, R0.y, R2;\n"
     5839    "MAD result.color.w, -R0, R1, R0.x;\n"
    59145840    "END\n"
    59155841    ;
     
    59235849    "TEMP R2;\n"
    59245850    "TEMP R3;\n"
    5925     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5926     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5927     "ADD R0.xyz, R0, c[2];\n"
    5928     "RCP R0.z, R0.z;\n"
    5929     "MUL R0.xy, R0, R0.z;\n"
    5930     "MUL R0.xy, R0, c[3];\n"
    5931     "MOV R0.y, -R0;\n"
    5932     "MUL R1.xy, fragment.position, c[4];\n"
     5851    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5852    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5853    "ADD R0.xyz, R0, c[3];\n"
     5854    "RCP R0.z, R0.z;\n"
     5855    "MUL R0.xy, R0, R0.z;\n"
     5856    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     5857    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5858    "MUL R0.xy, R0, c[0];\n"
    59335859    "TEX R0, R0, texture[1], 2D;\n"
    5934     "TEX R1, R1, texture[0], 2D;\n"
    59355860    "MUL R2.xyz, R0, R1.w;\n"
    5936     "MUL R3.xyz, R1, R0.w;\n"
     5861    "MUL R3.xyz, R0.w, R1;\n"
    59375862    "ADD R0.xyz, R0, R1;\n"
    59385863    "MIN R2.xyz, R2, R3;\n"
     
    59465871    "!!ARBfp1.0\n"
    59475872    "PARAM c[6] = { program.local[0..4],\n"
    5948     "           { 1, 2 } };\n"
    5949     "TEMP R0;\n"
    5950     "TEMP R1;\n"
    5951     "TEMP R2;\n"
    5952     "TEMP R3;\n"
    5953     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5954     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5955     "ADD R0.xyz, R0, c[2];\n"
    5956     "RCP R0.z, R0.z;\n"
    5957     "MUL R0.xy, R0, R0.z;\n"
    5958     "MUL R0.xy, R0, c[3];\n"
    5959     "MOV R0.y, -R0;\n"
    5960     "MUL R1.xy, fragment.position, c[4];\n"
    5961     "TEX R1, R1, texture[0], 2D;\n"
     5873    "           { 2, 1 } };\n"
     5874    "TEMP R0;\n"
     5875    "TEMP R1;\n"
     5876    "TEMP R2;\n"
     5877    "TEMP R3;\n"
     5878    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5879    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5880    "ADD R0.xyz, R0, c[3];\n"
     5881    "RCP R0.z, R0.z;\n"
     5882    "MUL R0.xy, R0, R0.z;\n"
     5883    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     5884    "TEX R1, R0.zwzw, texture[0], 2D;\n"
     5885    "MUL R0.xy, R0, c[0];\n"
    59625886    "TEX R0, R0, texture[1], 2D;\n"
    5963     "MUL R2.xyz, R1, R0.w;\n"
     5887    "MUL R2.xyz, R0.w, R1;\n"
    59645888    "MAD R3.xyz, R0, R1.w, R2;\n"
    59655889    "MUL R2.xyz, R0, R1;\n"
    5966     "MAD R2.xyz, -R2, c[5].y, R3;\n"
    5967     "ADD R2.w, -R1, c[5].x;\n"
     5890    "MAD R2.xyz, -R2, c[5].x, R3;\n"
     5891    "ADD R2.w, -R1, c[5].y;\n"
    59685892    "MAD R0.xyz, R0, R2.w, R2;\n"
    59695893    "ADD R2.x, R0.w, R1.w;\n"
    5970     "ADD R2.y, -R0.w, c[5].x;\n"
     5894    "ADD R2.y, -R0.w, c[5];\n"
    59715895    "MAD result.color.xyz, R1, R2.y, R0;\n"
    59725896    "MAD result.color.w, -R0, R1, R2.x;\n"
     
    59795903    "TEMP R0;\n"
    59805904    "TEMP R1;\n"
    5981     "MUL R0.xyz, fragment.position.y, c[1];\n"
    5982     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    5983     "ADD R1.xyz, R0, c[2];\n"
     5905    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5906    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5907    "ADD R1.xyz, R0, c[3];\n"
    59845908    "RCP R0.z, R1.z;\n"
    59855909    "MUL R1.xy, R1, R0.z;\n"
    5986     "ADD R0.xy, fragment.position, c[4];\n"
    5987     "MUL R0.xy, R0, c[5];\n"
     5910    "ADD R0.xy, fragment.position, c[5];\n"
     5911    "MUL R0.xy, R0, c[4];\n"
    59885912    "TEX R0, R0, texture[0], 2D;\n"
    59895913    "DP4 R1.z, R0, c[6];\n"
    5990     "MUL R1.xy, R1, c[3];\n"
    5991     "MOV R0.x, R1;\n"
    5992     "MOV R0.y, -R1;\n"
    5993     "TEX R0, R0, texture[1], 2D;\n"
     5914    "MUL R1.xy, R1, c[0];\n"
     5915    "TEX R0, R1, texture[1], 2D;\n"
    59945916    "MUL result.color, R0, R1.z;\n"
    59955917    "END\n"
     
    60005922    "PARAM c[4] = { program.local[0..3] };\n"
    60015923    "TEMP R0;\n"
    6002     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6003     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6004     "ADD R0.xyz, R0, c[2];\n"
    6005     "RCP R0.z, R0.z;\n"
    6006     "MUL R0.xy, R0, R0.z;\n"
    6007     "MUL R0.xy, R0, c[3];\n"
    6008     "MOV R0.y, -R0;\n"
     5924    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5925    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5926    "ADD R0.xyz, R0, c[3];\n"
     5927    "RCP R0.z, R0.z;\n"
     5928    "MUL R0.xy, R0, R0.z;\n"
     5929    "MUL R0.xy, R0, c[0];\n"
    60095930    "TEX result.color, R0, texture[0], 2D;\n"
    60105931    "END\n"
     
    60135934static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF =
    60145935    "!!ARBfp1.0\n"
    6015     "PARAM c[11] = { program.local[0..7],\n"
    6016     "           { 1 },\n"
    6017     "           program.local[9..10] };\n"
    6018     "TEMP R0;\n"
    6019     "TEMP R1;\n"
    6020     "TEMP R2;\n"
    6021     "TEMP R3;\n"
    6022     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6023     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6024     "ADD R0.xyz, R0, c[5];\n"
    6025     "RCP R0.z, R0.z;\n"
    6026     "MUL R0.xy, R0, R0.z;\n"
    6027     "MUL R0.xy, R0, c[6];\n"
    6028     "MOV R0.y, -R0;\n"
    6029     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    6030     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    6031     "TEX R0.x, R0, texture[2], 2D;\n"
    6032     "MUL R0, fragment.color.primary, R0.x;\n"
    6033     "MUL R2.xyz, R1, c[10].y;\n"
    6034     "MUL R3.xyz, R2, R0.w;\n"
    6035     "MUL R2.xyz, R0, c[10].x;\n"
    6036     "MAD R2.xyz, R2, R1.w, R3;\n"
    6037     "ADD R3.xy, fragment.position, c[0];\n"
    6038     "MUL R0.xyz, R0, c[9].y;\n"
    6039     "ADD R2.w, -R1, c[8].x;\n"
    6040     "MAD R2.xyz, R0, R2.w, R2;\n"
    6041     "ADD R2.w, -R0, c[8].x;\n"
    6042     "MUL R0.xyz, R1, c[9].z;\n"
    6043     "MAD R2.xyz, R0, R2.w, R2;\n"
    6044     "ADD R0.y, -R1.w, c[8].x;\n"
    6045     "MUL R0.z, R1.w, R2.w;\n"
    6046     "MUL R0.x, R0.w, R1.w;\n"
    6047     "MUL R0.y, R0.w, R0;\n"
    6048     "DP3 R2.w, R0, c[9];\n"
    6049     "MUL R3.xy, R3, c[1];\n"
    6050     "TEX R0, R3, texture[1], 2D;\n"
    6051     "ADD R2, R2, -R1;\n"
    6052     "DP4 R0.x, R0, c[2];\n"
    6053     "MAD result.color, R0.x, R2, R1;\n"
     5936    "PARAM c[11] = { program.local[0..9],\n"
     5937    "           { 1 } };\n"
     5938    "TEMP R0;\n"
     5939    "TEMP R1;\n"
     5940    "TEMP R2;\n"
     5941    "TEMP R3;\n"
     5942    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5943    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5944    "ADD R0.xyz, R0, c[3];\n"
     5945    "RCP R0.z, R0.z;\n"
     5946    "MUL R0.xy, R0, R0.z;\n"
     5947    "MUL R0.zw, R0.xyxy, c[0].xyxy;\n"
     5948    "TEX R1.x, R0.zwzw, texture[2], 2D;\n"
     5949    "MUL R0.xy, fragment.position, c[7];\n"
     5950    "TEX R0, R0, texture[0], 2D;\n"
     5951    "ADD R1.x, -R1, c[10];\n"
     5952    "MUL R1, fragment.color.primary, R1.x;\n"
     5953    "MUL R2.xyz, R0, c[4].y;\n"
     5954    "MUL R3.xyz, R1.w, R2;\n"
     5955    "MUL R2.xyz, R1, c[4].x;\n"
     5956    "MAD R2.xyz, R0.w, R2, R3;\n"
     5957    "ADD R3.xy, fragment.position, c[8];\n"
     5958    "ADD R2.w, -R0, c[10].x;\n"
     5959    "MUL R1.xyz, R1, c[5].y;\n"
     5960    "MAD R2.xyz, R2.w, R1, R2;\n"
     5961    "MUL R1.xyz, R0, c[5].z;\n"
     5962    "ADD R3.z, -R1.w, c[10].x;\n"
     5963    "MAD R2.xyz, R3.z, R1, R2;\n"
     5964    "MUL R1.y, R1.w, R2.w;\n"
     5965    "MUL R1.x, R1.w, R0.w;\n"
     5966    "MUL R1.z, R0.w, R3;\n"
     5967    "DP3 R2.w, R1, c[5];\n"
     5968    "MUL R3.xy, R3, c[6];\n"
     5969    "TEX R1, R3, texture[1], 2D;\n"
     5970    "ADD R2, R2, -R0;\n"
     5971    "DP4 R1.x, R1, c[9];\n"
     5972    "MAD result.color, R1.x, R2, R0;\n"
    60545973    "END\n"
    60555974    ;
     
    60625981    "TEMP R1;\n"
    60635982    "TEMP R2;\n"
    6064     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6065     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6066     "ADD R0.xyz, R0, c[5];\n"
    6067     "RCP R0.z, R0.z;\n"
    6068     "MUL R0.xy, R0, R0.z;\n"
    6069     "MUL R0.xy, R0, c[6];\n"
    6070     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    6071     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    6072     "MOV R0.y, -R0;\n"
     5983    "MUL R0.xyz, fragment.position.y, c[2];\n"
     5984    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     5985    "ADD R0.xyz, R0, c[3];\n"
     5986    "RCP R0.z, R0.z;\n"
     5987    "MUL R0.xy, R0, R0.z;\n"
     5988    "MUL R0.zw, R0.xyxy, c[0].xyxy;\n"
     5989    "TEX R1.x, R0.zwzw, texture[2], 2D;\n"
     5990    "MUL R0.xy, fragment.position, c[5];\n"
     5991    "TEX R0, R0, texture[0], 2D;\n"
     5992    "ADD R1.x, -R1, c[8];\n"
     5993    "MUL R1, fragment.color.primary, R1.x;\n"
     5994    "ADD R2.x, -R0.w, c[8];\n"
     5995    "MUL R2.xyz, R1, R2.x;\n"
     5996    "MAD R1.xyz, R1, R0, R2;\n"
     5997    "ADD R2.x, -R1.w, c[8];\n"
     5998    "MAD R2.xyz, R0, R2.x, R1;\n"
     5999    "ADD R1.z, R1.w, R0.w;\n"
     6000    "MAD R2.w, -R1, R0, R1.z;\n"
     6001    "ADD R1.xy, fragment.position, c[6];\n"
     6002    "MUL R1.xy, R1, c[4];\n"
     6003    "TEX R1, R1, texture[1], 2D;\n"
     6004    "ADD R2, R2, -R0;\n"
     6005    "DP4 R1.x, R1, c[7];\n"
     6006    "MAD result.color, R1.x, R2, R0;\n"
     6007    "END\n"
     6008    ;
     6009
     6010static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN =
     6011    "!!ARBfp1.0\n"
     6012    "PARAM c[9] = { program.local[0..7],\n"
     6013    "           { 1 } };\n"
     6014    "TEMP R0;\n"
     6015    "TEMP R1;\n"
     6016    "TEMP R2;\n"
     6017    "TEMP R3;\n"
     6018    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6019    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6020    "ADD R0.xyz, R0, c[3];\n"
     6021    "RCP R0.z, R0.z;\n"
     6022    "MUL R0.xy, R0, R0.z;\n"
     6023    "MUL R0.xy, R0, c[0];\n"
    60736024    "TEX R0.x, R0, texture[2], 2D;\n"
    6074     "MUL R0, fragment.color.primary, R0.x;\n"
    6075     "ADD R2.x, -R1.w, c[8];\n"
    6076     "MUL R2.xyz, R0, R2.x;\n"
    6077     "MAD R0.xyz, R0, R1, R2;\n"
    6078     "ADD R2.x, -R0.w, c[8];\n"
    6079     "MAD R2.xyz, R1, R2.x, R0;\n"
    6080     "ADD R0.z, R0.w, R1.w;\n"
    6081     "MAD R2.w, -R0, R1, R0.z;\n"
    6082     "ADD R0.xy, fragment.position, c[0];\n"
    6083     "MUL R0.xy, R0, c[1];\n"
    6084     "TEX R0, R0, texture[1], 2D;\n"
    6085     "ADD R2, R2, -R1;\n"
    6086     "DP4 R0.x, R0, c[2];\n"
    6087     "MAD result.color, R0.x, R2, R1;\n"
    6088     "END\n"
    6089     ;
    6090 
    6091 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN =
    6092     "!!ARBfp1.0\n"
    6093     "PARAM c[8] = { program.local[0..7] };\n"
    6094     "TEMP R0;\n"
    6095     "TEMP R1;\n"
    6096     "TEMP R2;\n"
    6097     "TEMP R3;\n"
    6098     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6099     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6100     "ADD R0.xyz, R0, c[5];\n"
    6101     "RCP R0.z, R0.z;\n"
    6102     "MUL R0.xy, R0, R0.z;\n"
    6103     "MUL R0.xy, R0, c[6];\n"
    6104     "MOV R0.y, -R0;\n"
    6105     "TEX R1.x, R0, texture[2], 2D;\n"
    6106     "MUL R0.xy, fragment.position, c[7];\n"
    6107     "ADD R3.xy, fragment.position, c[0];\n"
     6025    "ADD R0.z, -R0.x, c[8].x;\n"
     6026    "ADD R3.xy, fragment.position, c[6];\n"
     6027    "MUL R1, fragment.color.primary, R0.z;\n"
     6028    "MUL R0.xy, fragment.position, c[5];\n"
    61086029    "TEX R0, R0, texture[0], 2D;\n"
    6109     "MUL R1, fragment.color.primary, R1.x;\n"
    61106030    "ADD R2, R1, R0;\n"
    61116031    "MAD R2, -R1, R0, R2;\n"
    6112     "MUL R3.xy, R3, c[1];\n"
     6032    "MUL R3.xy, R3, c[4];\n"
    61136033    "TEX R1, R3, texture[1], 2D;\n"
    61146034    "ADD R2, R2, -R0;\n"
    6115     "DP4 R1.x, R1, c[2];\n"
     6035    "DP4 R1.x, R1, c[7];\n"
    61166036    "MAD result.color, R1.x, R2, R0;\n"
    61176037    "END\n"
     
    61216041    "!!ARBfp1.0\n"
    61226042    "PARAM c[9] = { program.local[0..7],\n"
    6123     "           { 2, 1 } };\n"
     6043    "           { 1, 2 } };\n"
    61246044    "TEMP R0;\n"
    61256045    "TEMP R1;\n"
     
    61276047    "TEMP R3;\n"
    61286048    "TEMP R4;\n"
    6129     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6130     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6131     "ADD R0.xyz, R0, c[5];\n"
    6132     "RCP R0.z, R0.z;\n"
    6133     "MUL R0.xy, R0, R0.z;\n"
    6134     "MUL R0.xy, R0, c[6];\n"
    6135     "MOV R0.y, -R0;\n"
    6136     "TEX R1.x, R0, texture[2], 2D;\n"
    6137     "MUL R1, fragment.color.primary, R1.x;\n"
    6138     "MUL R0.xy, fragment.position, c[7];\n"
    6139     "TEX R0, R0, texture[0], 2D;\n"
    6140     "ADD R2.w, -R0, c[8].y;\n"
     6049    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6050    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6051    "ADD R0.xyz, R0, c[3];\n"
     6052    "RCP R0.z, R0.z;\n"
     6053    "MUL R0.xy, R0, R0.z;\n"
     6054    "MUL R0.xy, R0, c[0];\n"
     6055    "TEX R0.x, R0, texture[2], 2D;\n"
     6056    "ADD R0.x, -R0, c[8];\n"
     6057    "MUL R1, fragment.color.primary, R0.x;\n"
     6058    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     6059    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6060    "ADD R2.w, -R0, c[8].x;\n"
    61416061    "ADD R3.xyz, R1.w, -R1;\n"
    61426062    "ADD R2.xyz, R0.w, -R0;\n"
    61436063    "MUL R2.xyz, R2, R3;\n"
    6144     "MUL R2.xyz, R2, c[8].x;\n"
     6064    "MUL R2.xyz, R2, c[8].y;\n"
    61456065    "MAD R2.xyz, R1.w, R0.w, -R2;\n"
    61466066    "MUL R4.xyz, R1, R2.w;\n"
    61476067    "MUL R3.xyz, R1, R0;\n"
    61486068    "MAD R1.xyz, R1, R2.w, R2;\n"
    6149     "ADD R2.x, -R1.w, c[8].y;\n"
    6150     "MAD R3.xyz, R3, c[8].x, R4;\n"
     6069    "ADD R2.x, -R1.w, c[8];\n"
     6070    "MAD R3.xyz, R3, c[8].y, R4;\n"
    61516071    "MAD R3.xyz, R0, R2.x, R3;\n"
    61526072    "MAD R1.xyz, R0, R2.x, R1;\n"
    6153     "MUL R2.xyz, R0, c[8].x;\n"
     6073    "MUL R2.xyz, R0, c[8].y;\n"
    61546074    "ADD R1.xyz, R1, -R3;\n"
    61556075    "SGE R2.xyz, R2, R0.w;\n"
     
    61576077    "ADD R1.z, R1.w, R0.w;\n"
    61586078    "MAD R2.w, -R1, R0, R1.z;\n"
    6159     "ADD R1.xy, fragment.position, c[0];\n"
    6160     "MUL R1.xy, R1, c[1];\n"
     6079    "ADD R1.xy, fragment.position, c[6];\n"
     6080    "MUL R1.xy, R1, c[4];\n"
    61616081    "TEX R1, R1, texture[1], 2D;\n"
    61626082    "ADD R2, R2, -R0;\n"
    6163     "DP4 R1.x, R1, c[2];\n"
     6083    "DP4 R1.x, R1, c[7];\n"
    61646084    "MAD result.color, R1.x, R2, R0;\n"
    61656085    "END\n"
     
    61746094    "TEMP R2;\n"
    61756095    "TEMP R3;\n"
    6176     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6177     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6178     "ADD R0.xyz, R0, c[5];\n"
    6179     "RCP R0.z, R0.z;\n"
    6180     "MUL R0.xy, R0, R0.z;\n"
    6181     "MUL R0.xy, R0, c[6];\n"
    6182     "MOV R0.y, -R0;\n"
    6183     "TEX R0.x, R0, texture[2], 2D;\n"
    6184     "MUL R1.xy, fragment.position, c[7];\n"
    6185     "TEX R1, R1, texture[0], 2D;\n"
    6186     "MUL R0, fragment.color.primary, R0.x;\n"
    6187     "MUL R3.xyz, R1, R0.w;\n"
    6188     "MUL R2.xyz, R0, R1.w;\n"
     6096    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6097    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6098    "ADD R0.xyz, R0, c[3];\n"
     6099    "RCP R0.z, R0.z;\n"
     6100    "MUL R0.xy, R0, R0.z;\n"
     6101    "MUL R0.xy, R0, c[0];\n"
     6102    "TEX R1.x, R0, texture[2], 2D;\n"
     6103    "MUL R0.xy, fragment.position, c[5];\n"
     6104    "TEX R0, R0, texture[0], 2D;\n"
     6105    "ADD R1.x, -R1, c[8];\n"
     6106    "MUL R1, fragment.color.primary, R1.x;\n"
     6107    "MUL R3.xyz, R1.w, R0;\n"
     6108    "MUL R2.xyz, R1, R0.w;\n"
    61896109    "MIN R2.xyz, R2, R3;\n"
    6190     "ADD R2.w, -R1, c[8].x;\n"
    6191     "MAD R0.xyz, R0, R2.w, R2;\n"
    6192     "ADD R2.x, -R0.w, c[8];\n"
    6193     "MAD R2.xyz, R1, R2.x, R0;\n"
    6194     "ADD R0.z, R0.w, R1.w;\n"
    6195     "MAD R2.w, -R0, R1, R0.z;\n"
    6196     "ADD R0.xy, fragment.position, c[0];\n"
    6197     "MUL R0.xy, R0, c[1];\n"
    6198     "TEX R0, R0, texture[1], 2D;\n"
    6199     "ADD R2, R2, -R1;\n"
    6200     "DP4 R0.x, R0, c[2];\n"
    6201     "MAD result.color, R0.x, R2, R1;\n"
     6110    "ADD R2.w, -R0, c[8].x;\n"
     6111    "MAD R1.xyz, R1, R2.w, R2;\n"
     6112    "ADD R2.x, -R1.w, c[8];\n"
     6113    "MAD R2.xyz, R0, R2.x, R1;\n"
     6114    "ADD R1.z, R1.w, R0.w;\n"
     6115    "MAD R2.w, -R1, R0, R1.z;\n"
     6116    "ADD R1.xy, fragment.position, c[6];\n"
     6117    "MUL R1.xy, R1, c[4];\n"
     6118    "TEX R1, R1, texture[1], 2D;\n"
     6119    "ADD R2, R2, -R0;\n"
     6120    "DP4 R1.x, R1, c[7];\n"
     6121    "MAD result.color, R1.x, R2, R0;\n"
    62026122    "END\n"
    62036123    ;
     
    62116131    "TEMP R2;\n"
    62126132    "TEMP R3;\n"
    6213     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6214     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6215     "ADD R0.xyz, R0, c[5];\n"
    6216     "RCP R0.z, R0.z;\n"
    6217     "MUL R0.xy, R0, R0.z;\n"
    6218     "MUL R0.xy, R0, c[6];\n"
    6219     "MOV R0.y, -R0;\n"
     6133    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6134    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6135    "ADD R0.xyz, R0, c[3];\n"
     6136    "RCP R0.z, R0.z;\n"
     6137    "MUL R0.xy, R0, R0.z;\n"
     6138    "MUL R0.xy, R0, c[0];\n"
     6139    "TEX R1.x, R0, texture[2], 2D;\n"
     6140    "MUL R0.xy, fragment.position, c[5];\n"
     6141    "TEX R0, R0, texture[0], 2D;\n"
     6142    "ADD R1.x, -R1, c[8];\n"
     6143    "MUL R1, fragment.color.primary, R1.x;\n"
     6144    "MUL R3.xyz, R1.w, R0;\n"
     6145    "MUL R2.xyz, R1, R0.w;\n"
     6146    "MAX R2.xyz, R2, R3;\n"
     6147    "ADD R2.w, -R0, c[8].x;\n"
     6148    "MAD R1.xyz, R1, R2.w, R2;\n"
     6149    "ADD R2.x, -R1.w, c[8];\n"
     6150    "MAD R2.xyz, R0, R2.x, R1;\n"
     6151    "ADD R1.z, R1.w, R0.w;\n"
     6152    "MAD R2.w, -R1, R0, R1.z;\n"
     6153    "ADD R1.xy, fragment.position, c[6];\n"
     6154    "MUL R1.xy, R1, c[4];\n"
     6155    "TEX R1, R1, texture[1], 2D;\n"
     6156    "ADD R2, R2, -R0;\n"
     6157    "DP4 R1.x, R1, c[7];\n"
     6158    "MAD result.color, R1.x, R2, R0;\n"
     6159    "END\n"
     6160    ;
     6161
     6162static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE =
     6163    "!!ARBfp1.0\n"
     6164    "PARAM c[9] = { program.local[0..7],\n"
     6165    "           { 1, 1e-006 } };\n"
     6166    "TEMP R0;\n"
     6167    "TEMP R1;\n"
     6168    "TEMP R2;\n"
     6169    "TEMP R3;\n"
     6170    "TEMP R4;\n"
     6171    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6172    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6173    "ADD R0.xyz, R0, c[3];\n"
     6174    "RCP R0.z, R0.z;\n"
     6175    "MUL R0.xy, R0, R0.z;\n"
     6176    "MUL R0.xy, R0, c[0];\n"
    62206177    "TEX R0.x, R0, texture[2], 2D;\n"
    6221     "MUL R1.xy, fragment.position, c[7];\n"
    6222     "TEX R1, R1, texture[0], 2D;\n"
    6223     "MUL R0, fragment.color.primary, R0.x;\n"
    6224     "MUL R3.xyz, R1, R0.w;\n"
    6225     "MUL R2.xyz, R0, R1.w;\n"
    6226     "MAX R2.xyz, R2, R3;\n"
    6227     "ADD R2.w, -R1, c[8].x;\n"
    6228     "MAD R0.xyz, R0, R2.w, R2;\n"
    6229     "ADD R2.x, -R0.w, c[8];\n"
    6230     "MAD R2.xyz, R1, R2.x, R0;\n"
    6231     "ADD R0.z, R0.w, R1.w;\n"
    6232     "MAD R2.w, -R0, R1, R0.z;\n"
    6233     "ADD R0.xy, fragment.position, c[0];\n"
    6234     "MUL R0.xy, R0, c[1];\n"
    6235     "TEX R0, R0, texture[1], 2D;\n"
    6236     "ADD R2, R2, -R1;\n"
    6237     "DP4 R0.x, R0, c[2];\n"
    6238     "MAD result.color, R0.x, R2, R1;\n"
    6239     "END\n"
    6240     ;
    6241 
    6242 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_COLORDODGE =
    6243     "!!ARBfp1.0\n"
    6244     "PARAM c[9] = { program.local[0..7],\n"
    6245     "           { 1, 1e-06 } };\n"
    6246     "TEMP R0;\n"
    6247     "TEMP R1;\n"
    6248     "TEMP R2;\n"
    6249     "TEMP R3;\n"
    6250     "TEMP R4;\n"
    6251     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6252     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6253     "ADD R0.xyz, R0, c[5];\n"
    6254     "RCP R0.z, R0.z;\n"
    6255     "MUL R0.xy, R0, R0.z;\n"
    6256     "MUL R0.xy, R0, c[6];\n"
    6257     "MOV R0.y, -R0;\n"
    6258     "TEX R0.x, R0, texture[2], 2D;\n"
     6178    "ADD R0.x, -R0, c[8];\n"
    62596179    "MUL R1, fragment.color.primary, R0.x;\n"
    62606180    "MAX R0.x, R1.w, c[8].y;\n"
    62616181    "RCP R0.x, R0.x;\n"
    6262     "MAD R0.xyz, -R1, R0.x, c[8].x;\n"
    6263     "MAX R2.xyz, R0, c[8].y;\n"
    6264     "MUL R0.xy, fragment.position, c[7];\n"
     6182    "MAD R2.xyz, -R1, R0.x, c[8].x;\n"
     6183    "MAX R2.xyz, R2, c[8].y;\n"
     6184    "MUL R0.xy, fragment.position, c[5];\n"
    62656185    "TEX R0, R0, texture[0], 2D;\n"
    62666186    "ADD R2.w, -R1, c[8].x;\n"
     
    62686188    "ADD R2.w, -R0, c[8].x;\n"
    62696189    "MAD R4.xyz, R1, R2.w, R3;\n"
    6270     "MUL R3.xyz, R0, R1.w;\n"
     6190    "MUL R3.xyz, R1.w, R0;\n"
    62716191    "MUL R2.w, R1, R0;\n"
    62726192    "MAD R1.xyz, R1, R0.w, R3;\n"
     
    62816201    "ADD R1.z, R1.w, R0.w;\n"
    62826202    "MAD R2.w, -R1, R0, R1.z;\n"
    6283     "ADD R1.xy, fragment.position, c[0];\n"
    6284     "MUL R1.xy, R1, c[1];\n"
     6203    "ADD R1.xy, fragment.position, c[6];\n"
     6204    "MUL R1.xy, R1, c[4];\n"
    62856205    "TEX R1, R1, texture[1], 2D;\n"
    62866206    "ADD R2, R2, -R0;\n"
    6287     "DP4 R1.x, R1, c[2];\n"
     6207    "DP4 R1.x, R1, c[7];\n"
    62886208    "MAD result.color, R1.x, R2, R0;\n"
    62896209    "END\n"
     
    62936213    "!!ARBfp1.0\n"
    62946214    "PARAM c[9] = { program.local[0..7],\n"
    6295     "           { 1, 9.9999997e-06 } };\n"
     6215    "           { 1, 9.9999997e-006 } };\n"
    62966216    "TEMP R0;\n"
    62976217    "TEMP R1;\n"
     
    63006220    "TEMP R4;\n"
    63016221    "TEMP R5;\n"
    6302     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6303     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6304     "ADD R0.xyz, R0, c[5];\n"
    6305     "RCP R0.z, R0.z;\n"
    6306     "MUL R0.xy, R0, R0.z;\n"
    6307     "MUL R0.xy, R0, c[6];\n"
    6308     "MOV R0.y, -R0;\n"
    6309     "TEX R1.x, R0, texture[2], 2D;\n"
     6222    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6223    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6224    "ADD R0.xyz, R0, c[3];\n"
     6225    "RCP R0.z, R0.z;\n"
     6226    "MUL R0.xy, R0, R0.z;\n"
     6227    "MUL R0.xy, R0, c[0];\n"
     6228    "TEX R0.x, R0, texture[2], 2D;\n"
     6229    "ADD R1.x, -R0, c[8];\n"
    63106230    "MUL R1, fragment.color.primary, R1.x;\n"
    6311     "MUL R0.xy, fragment.position, c[7];\n"
    6312     "TEX R0, R0, texture[0], 2D;\n"
    6313     "MUL R2.xyz, R0, R1.w;\n"
     6231    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     6232    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6233    "MUL R2.xyz, R1.w, R0;\n"
    63146234    "MAD R3.xyz, R1, R0.w, R2;\n"
    63156235    "MAD R2.xyz, -R1.w, R0.w, R3;\n"
     
    63266246    "MAD R1.xyz, R1, R2.w, R4;\n"
    63276247    "MUL R2.w, R1, R0;\n"
    6328     "ADD R3.w, -R1, c[8].x;\n"
    63296248    "MAD R2.xyz, R0, R3.w, R2;\n"
    63306249    "ADD R2.xyz, R2, -R1;\n"
     
    63336252    "ADD R1.z, R1.w, R0.w;\n"
    63346253    "MAD R2.w, -R1, R0, R1.z;\n"
    6335     "ADD R1.xy, fragment.position, c[0];\n"
    6336     "MUL R1.xy, R1, c[1];\n"
     6254    "ADD R1.xy, fragment.position, c[6];\n"
     6255    "MUL R1.xy, R1, c[4];\n"
    63376256    "TEX R1, R1, texture[1], 2D;\n"
    63386257    "ADD R2, R2, -R0;\n"
    6339     "DP4 R1.x, R1, c[2];\n"
     6258    "DP4 R1.x, R1, c[7];\n"
    63406259    "MAD result.color, R1.x, R2, R0;\n"
    63416260    "END\n"
     
    63456264    "!!ARBfp1.0\n"
    63466265    "PARAM c[9] = { program.local[0..7],\n"
    6347     "           { 2, 1 } };\n"
     6266    "           { 1, 2 } };\n"
    63486267    "TEMP R0;\n"
    63496268    "TEMP R1;\n"
     
    63516270    "TEMP R3;\n"
    63526271    "TEMP R4;\n"
    6353     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6354     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6355     "ADD R0.xyz, R0, c[5];\n"
    6356     "RCP R0.z, R0.z;\n"
    6357     "MUL R0.xy, R0, R0.z;\n"
    6358     "MUL R0.xy, R0, c[6];\n"
    6359     "MOV R0.y, -R0;\n"
    6360     "TEX R1.x, R0, texture[2], 2D;\n"
    6361     "MUL R1, fragment.color.primary, R1.x;\n"
    6362     "MUL R0.xy, fragment.position, c[7];\n"
    6363     "TEX R0, R0, texture[0], 2D;\n"
    6364     "ADD R2.w, -R0, c[8].y;\n"
     6272    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6273    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6274    "ADD R0.xyz, R0, c[3];\n"
     6275    "RCP R0.z, R0.z;\n"
     6276    "MUL R0.xy, R0, R0.z;\n"
     6277    "MUL R0.xy, R0, c[0];\n"
     6278    "TEX R0.x, R0, texture[2], 2D;\n"
     6279    "ADD R0.x, -R0, c[8];\n"
     6280    "MUL R1, fragment.color.primary, R0.x;\n"
     6281    "MUL R0.zw, fragment.position.xyxy, c[5].xyxy;\n"
     6282    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6283    "ADD R2.w, -R0, c[8].x;\n"
    63656284    "ADD R3.xyz, R1.w, -R1;\n"
    63666285    "ADD R2.xyz, R0.w, -R0;\n"
    63676286    "MUL R2.xyz, R2, R3;\n"
    6368     "MUL R2.xyz, R2, c[8].x;\n"
     6287    "MUL R2.xyz, R2, c[8].y;\n"
    63696288    "MAD R2.xyz, R1.w, R0.w, -R2;\n"
    63706289    "MUL R4.xyz, R1, R2.w;\n"
    63716290    "MAD R2.xyz, R1, R2.w, R2;\n"
    63726291    "MUL R3.xyz, R1, R0;\n"
    6373     "ADD R2.w, -R1, c[8].y;\n"
    6374     "MAD R3.xyz, R3, c[8].x, R4;\n"
    6375     "MUL R1.xyz, R1, c[8].x;\n"
     6292    "ADD R2.w, -R1, c[8].x;\n"
     6293    "MAD R3.xyz, R3, c[8].y, R4;\n"
     6294    "MUL R1.xyz, R1, c[8].y;\n"
    63766295    "SGE R1.xyz, R1, R1.w;\n"
    63776296    "MAD R3.xyz, R0, R2.w, R3;\n"
     
    63816300    "ADD R1.z, R1.w, R0.w;\n"
    63826301    "MAD R2.w, -R1, R0, R1.z;\n"
    6383     "ADD R1.xy, fragment.position, c[0];\n"
    6384     "MUL R1.xy, R1, c[1];\n"
     6302    "ADD R1.xy, fragment.position, c[6];\n"
     6303    "MUL R1.xy, R1, c[4];\n"
    63856304    "TEX R1, R1, texture[1], 2D;\n"
    63866305    "ADD R2, R2, -R0;\n"
    6387     "DP4 R1.x, R1, c[2];\n"
     6306    "DP4 R1.x, R1, c[7];\n"
    63886307    "MAD result.color, R1.x, R2, R0;\n"
    63896308    "END\n"
     
    63936312    "!!ARBfp1.0\n"
    63946313    "PARAM c[10] = { program.local[0..7],\n"
    6395     "           { 1, 9.9999997e-06, 2, 8 },\n"
    6396     "           { 3 } };\n"
     6314    "           { 1, 2, 9.9999997e-006, 4 },\n"
     6315    "           { 16, 12, 3 } };\n"
    63976316    "TEMP R0;\n"
    63986317    "TEMP R1;\n"
     
    64016320    "TEMP R4;\n"
    64026321    "TEMP R5;\n"
    6403     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6404     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6405     "ADD R1.xyz, R0, c[5];\n"
    6406     "RCP R0.z, R1.z;\n"
    6407     "MUL R1.xy, R1, R0.z;\n"
    6408     "MUL R1.xy, R1, c[6];\n"
    6409     "MOV R1.y, -R1;\n"
    6410     "MUL R0.xy, fragment.position, c[7];\n"
     6322    "TEMP R6;\n"
     6323    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6324    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6325    "ADD R1.xyz, R0, c[3];\n"
     6326    "RCP R1.z, R1.z;\n"
     6327    "MUL R1.xy, R1, R1.z;\n"
     6328    "MUL R1.xy, R1, c[0];\n"
     6329    "TEX R1.x, R1, texture[2], 2D;\n"
     6330    "MUL R0.xy, fragment.position, c[5];\n"
    64116331    "TEX R0, R0, texture[0], 2D;\n"
    6412     "MAX R1.z, R0.w, c[8].y;\n"
    6413     "RCP R2.w, R1.z;\n"
    6414     "MUL R2.xyz, R0, R2.w;\n"
    6415     "MUL R5.xyz, -R2, c[8].w;\n"
    6416     "MAD R4.xyz, -R0, R2.w, c[8].x;\n"
    6417     "TEX R1.x, R1, texture[2], 2D;\n"
     6332    "MAX R1.z, R0.w, c[8];\n"
     6333    "RCP R1.z, R1.z;\n"
     6334    "MUL R3.xyz, R0, R1.z;\n"
     6335    "MAD R2.xyz, R3, c[9].x, -c[9].y;\n"
     6336    "ADD R1.x, -R1, c[8];\n"
    64186337    "MUL R1, fragment.color.primary, R1.x;\n"
    6419     "MAD R3.xyz, R1, c[8].z, -R1.w;\n"
    6420     "RSQ R2.x, R2.x;\n"
    6421     "RSQ R2.z, R2.z;\n"
    6422     "RSQ R2.y, R2.y;\n"
    6423     "MUL R4.xyz, R4, R3;\n"
    6424     "ADD R5.xyz, R5, c[9].x;\n"
    6425     "MUL R5.xyz, R4, R5;\n"
    6426     "ADD R4.xyz, R1.w, -R4;\n"
     6338    "MAD R4.xyz, R3, R2, c[9].z;\n"
     6339    "MAD R2.xyz, R1, c[8].y, -R1.w;\n"
     6340    "MUL R5.xyz, R0.w, R2;\n"
     6341    "MUL R6.xyz, R5, R4;\n"
     6342    "RSQ R2.w, R3.x;\n"
     6343    "RCP R4.x, R2.w;\n"
     6344    "RSQ R2.w, R3.y;\n"
     6345    "RSQ R3.w, R3.z;\n"
     6346    "RCP R4.y, R2.w;\n"
     6347    "RCP R4.z, R3.w;\n"
     6348    "ADD R4.xyz, -R3, R4;\n"
     6349    "MUL R6.xyz, R3, R6;\n"
     6350    "MUL R4.xyz, R5, R4;\n"
     6351    "ADD R3.xyz, -R3, c[8].x;\n"
     6352    "MAD R2.xyz, R2, R3, R1.w;\n"
     6353    "MUL R3.xyz, R1, c[8].y;\n"
     6354    "MAD R5.xyz, R1.w, R0, R6;\n"
     6355    "MAD R4.xyz, R1.w, R0, R4;\n"
     6356    "ADD R6.xyz, R4, -R5;\n"
     6357    "MUL R4.xyz, R0, c[8].w;\n"
     6358    "SGE R4.xyz, R4, R0.w;\n"
     6359    "MAD R4.xyz, R4, R6, R5;\n"
     6360    "MAD R4.xyz, -R0, R2, R4;\n"
     6361    "SGE R3.xyz, R3, R1.w;\n"
     6362    "MUL R2.xyz, R0, R2;\n"
    64276363    "ADD R2.w, -R0, c[8].x;\n"
    6428     "RCP R2.x, R2.x;\n"
    6429     "RCP R2.z, R2.z;\n"
    6430     "RCP R2.y, R2.y;\n"
    6431     "MAD R2.xyz, R2, R0.w, -R0;\n"
    6432     "MUL R3.xyz, R2, R3;\n"
    6433     "ADD R2.xyz, R1.w, -R5;\n"
    6434     "MAD R5.xyz, R0, R1.w, R3;\n"
    6435     "MUL R2.xyz, R0, R2;\n"
    6436     "MUL R3.xyz, R0, c[8].w;\n"
    6437     "ADD R5.xyz, R5, -R2;\n"
    6438     "SGE R3.xyz, R3, R0.w;\n"
    6439     "MUL R3.xyz, R3, R5;\n"
    6440     "ADD R2.xyz, R2, R3;\n"
    6441     "MUL R3.xyz, R0, R4;\n"
    6442     "MUL R4.xyz, R1, c[8].z;\n"
    6443     "SGE R4.xyz, R4, R1.w;\n"
    6444     "ADD R2.xyz, R2, -R3;\n"
    6445     "MUL R2.xyz, R4, R2;\n"
    6446     "ADD R2.xyz, R3, R2;\n"
     6364    "MAD R2.xyz, R3, R4, R2;\n"
     6365    "MAD R2.xyz, R1, R2.w, R2;\n"
     6366    "ADD R1.x, -R1.w, c[8];\n"
     6367    "MAD R2.xyz, R0, R1.x, R2;\n"
     6368    "ADD R1.z, R1.w, R0.w;\n"
     6369    "MAD R2.w, -R1, R0, R1.z;\n"
     6370    "ADD R1.xy, fragment.position, c[6];\n"
     6371    "MUL R1.xy, R1, c[4];\n"
     6372    "TEX R1, R1, texture[1], 2D;\n"
     6373    "ADD R2, R2, -R0;\n"
     6374    "DP4 R1.x, R1, c[7];\n"
     6375    "MAD result.color, R1.x, R2, R0;\n"
     6376    "END\n"
     6377    ;
     6378
     6379static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE =
     6380    "!!ARBfp1.0\n"
     6381    "PARAM c[9] = { program.local[0..7],\n"
     6382    "           { 1, 2 } };\n"
     6383    "TEMP R0;\n"
     6384    "TEMP R1;\n"
     6385    "TEMP R2;\n"
     6386    "TEMP R3;\n"
     6387    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6388    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6389    "ADD R0.xyz, R0, c[3];\n"
     6390    "RCP R0.z, R0.z;\n"
     6391    "MUL R0.xy, R0, R0.z;\n"
     6392    "MUL R0.xy, R0, c[0];\n"
     6393    "TEX R1.x, R0, texture[2], 2D;\n"
     6394    "MUL R0.xy, fragment.position, c[5];\n"
     6395    "ADD R1.x, -R1, c[8];\n"
     6396    "TEX R0, R0, texture[0], 2D;\n"
     6397    "MUL R1, fragment.color.primary, R1.x;\n"
     6398    "ADD R2.xyz, R1, R0;\n"
     6399    "MUL R3.xyz, R1.w, R0;\n"
     6400    "MUL R1.xyz, R1, R0.w;\n"
     6401    "MIN R1.xyz, R1, R3;\n"
     6402    "MAD R2.xyz, -R1, c[8].y, R2;\n"
     6403    "ADD R1.z, R1.w, R0.w;\n"
     6404    "MAD R2.w, -R1, R0, R1.z;\n"
     6405    "ADD R1.xy, fragment.position, c[6];\n"
     6406    "MUL R1.xy, R1, c[4];\n"
     6407    "TEX R1, R1, texture[1], 2D;\n"
     6408    "ADD R2, R2, -R0;\n"
     6409    "DP4 R1.x, R1, c[7];\n"
     6410    "MAD result.color, R1.x, R2, R0;\n"
     6411    "END\n"
     6412    ;
     6413
     6414static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION =
     6415    "!!ARBfp1.0\n"
     6416    "PARAM c[9] = { program.local[0..7],\n"
     6417    "           { 1, 2 } };\n"
     6418    "TEMP R0;\n"
     6419    "TEMP R1;\n"
     6420    "TEMP R2;\n"
     6421    "TEMP R3;\n"
     6422    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6423    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6424    "ADD R0.xyz, R0, c[3];\n"
     6425    "RCP R0.z, R0.z;\n"
     6426    "MUL R0.xy, R0, R0.z;\n"
     6427    "MUL R0.xy, R0, c[0];\n"
     6428    "TEX R1.x, R0, texture[2], 2D;\n"
     6429    "MUL R0.xy, fragment.position, c[5];\n"
     6430    "TEX R0, R0, texture[0], 2D;\n"
     6431    "ADD R1.x, -R1, c[8];\n"
     6432    "MUL R1, fragment.color.primary, R1.x;\n"
     6433    "MUL R2.xyz, R1.w, R0;\n"
     6434    "MAD R3.xyz, R1, R0.w, R2;\n"
     6435    "MUL R2.xyz, R1, R0;\n"
     6436    "MAD R2.xyz, -R2, c[8].y, R3;\n"
     6437    "ADD R2.w, -R0, c[8].x;\n"
    64476438    "MAD R1.xyz, R1, R2.w, R2;\n"
    64486439    "ADD R2.x, -R1.w, c[8];\n"
     
    64506441    "ADD R1.z, R1.w, R0.w;\n"
    64516442    "MAD R2.w, -R1, R0, R1.z;\n"
    6452     "ADD R1.xy, fragment.position, c[0];\n"
    6453     "MUL R1.xy, R1, c[1];\n"
     6443    "ADD R1.xy, fragment.position, c[6];\n"
     6444    "MUL R1.xy, R1, c[4];\n"
    64546445    "TEX R1, R1, texture[1], 2D;\n"
    64556446    "ADD R2, R2, -R0;\n"
    6456     "DP4 R1.x, R1, c[2];\n"
     6447    "DP4 R1.x, R1, c[7];\n"
    64576448    "MAD result.color, R1.x, R2, R0;\n"
    64586449    "END\n"
    64596450    ;
    64606451
    6461 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_DIFFERENCE =
    6462     "!!ARBfp1.0\n"
    6463     "PARAM c[9] = { program.local[0..7],\n"
    6464     "           { 2 } };\n"
    6465     "TEMP R0;\n"
    6466     "TEMP R1;\n"
    6467     "TEMP R2;\n"
    6468     "TEMP R3;\n"
    6469     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6470     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6471     "ADD R0.xyz, R0, c[5];\n"
    6472     "RCP R0.z, R0.z;\n"
    6473     "MUL R0.xy, R0, R0.z;\n"
    6474     "MUL R0.xy, R0, c[6];\n"
    6475     "MOV R0.y, -R0;\n"
    6476     "MUL R0.zw, fragment.position.xyxy, c[7].xyxy;\n"
    6477     "TEX R1, R0.zwzw, texture[0], 2D;\n"
    6478     "TEX R0.x, R0, texture[2], 2D;\n"
    6479     "MUL R0, fragment.color.primary, R0.x;\n"
    6480     "ADD R3.xyz, R0, R1;\n"
    6481     "MUL R2.xyz, R1, R0.w;\n"
    6482     "MUL R0.xyz, R0, R1.w;\n"
    6483     "MIN R0.xyz, R0, R2;\n"
    6484     "MAD R2.xyz, -R0, c[8].x, R3;\n"
    6485     "ADD R0.z, R0.w, R1.w;\n"
    6486     "MAD R2.w, -R0, R1, R0.z;\n"
    6487     "ADD R0.xy, fragment.position, c[0];\n"
    6488     "MUL R0.xy, R0, c[1];\n"
    6489     "TEX R0, R0, texture[1], 2D;\n"
    6490     "ADD R2, R2, -R1;\n"
    6491     "DP4 R0.x, R0, c[2];\n"
    6492     "MAD result.color, R0.x, R2, R1;\n"
    6493     "END\n"
    6494     ;
    6495 
    6496 static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_EXCLUSION =
    6497     "!!ARBfp1.0\n"
    6498     "PARAM c[9] = { program.local[0..7],\n"
    6499     "           { 1, 2 } };\n"
    6500     "TEMP R0;\n"
    6501     "TEMP R1;\n"
    6502     "TEMP R2;\n"
    6503     "TEMP R3;\n"
    6504     "MUL R0.xyz, fragment.position.y, c[4];\n"
    6505     "MAD R0.xyz, fragment.position.x, c[3], R0;\n"
    6506     "ADD R0.xyz, R0, c[5];\n"
    6507     "RCP R0.z, R0.z;\n"
    6508     "MUL R0.xy, R0, R0.z;\n"
    6509     "MUL R0.xy, R0, c[6];\n"
    6510     "MOV R0.y, -R0;\n"
    6511     "TEX R0.x, R0, texture[2], 2D;\n"
    6512     "MUL R1.xy, fragment.position, c[7];\n"
    6513     "TEX R1, R1, texture[0], 2D;\n"
    6514     "MUL R0, fragment.color.primary, R0.x;\n"
    6515     "MUL R2.xyz, R1, R0.w;\n"
    6516     "MAD R3.xyz, R0, R1.w, R2;\n"
    6517     "MUL R2.xyz, R0, R1;\n"
    6518     "MAD R2.xyz, -R2, c[8].y, R3;\n"
    6519     "ADD R2.w, -R1, c[8].x;\n"
    6520     "MAD R0.xyz, R0, R2.w, R2;\n"
    6521     "ADD R2.x, -R0.w, c[8];\n"
    6522     "MAD R2.xyz, R1, R2.x, R0;\n"
    6523     "ADD R0.z, R0.w, R1.w;\n"
    6524     "MAD R2.w, -R0, R1, R0.z;\n"
    6525     "ADD R0.xy, fragment.position, c[0];\n"
    6526     "MUL R0.xy, R0, c[1];\n"
    6527     "TEX R0, R0, texture[1], 2D;\n"
    6528     "ADD R2, R2, -R1;\n"
    6529     "DP4 R0.x, R0, c[2];\n"
    6530     "MAD result.color, R0.x, R2, R1;\n"
    6531     "END\n"
    6532     ;
    6533 
    65346452static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SIMPLE_PORTER_DUFF_NOMASK =
    65356453    "!!ARBfp1.0\n"
    6536     "PARAM c[8] = { program.local[0..4],\n"
    6537     "           { 1 },\n"
    6538     "           program.local[6..7] };\n"
    6539     "TEMP R0;\n"
    6540     "TEMP R1;\n"
    6541     "TEMP R2;\n"
    6542     "TEMP R3;\n"
    6543     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6544     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6545     "ADD R0.xyz, R0, c[2];\n"
    6546     "RCP R0.z, R0.z;\n"
    6547     "MUL R0.xy, R0, R0.z;\n"
    6548     "MUL R0.xy, R0, c[3];\n"
    6549     "MOV R0.w, -R0.y;\n"
    6550     "MOV R0.z, R0.x;\n"
    6551     "TEX R1.x, R0.zwzw, texture[1], 2D;\n"
    6552     "MUL R0.xy, fragment.position, c[4];\n"
    6553     "TEX R0, R0, texture[0], 2D;\n"
    6554     "MUL R2.xyz, R0, c[7].y;\n"
     6454    "PARAM c[8] = { program.local[0..6],\n"
     6455    "           { 1 } };\n"
     6456    "TEMP R0;\n"
     6457    "TEMP R1;\n"
     6458    "TEMP R2;\n"
     6459    "TEMP R3;\n"
     6460    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6461    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6462    "ADD R0.xyz, R0, c[3];\n"
     6463    "RCP R0.z, R0.z;\n"
     6464    "MUL R0.xy, R0, R0.z;\n"
     6465    "MUL R0.xy, R0, c[0];\n"
     6466    "TEX R1.x, R0, texture[1], 2D;\n"
     6467    "MUL R0.zw, fragment.position.xyxy, c[6].xyxy;\n"
     6468    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6469    "MUL R2.xyz, R0, c[4].y;\n"
     6470    "ADD R1.x, -R1, c[7];\n"
    65556471    "MUL R1, fragment.color.primary, R1.x;\n"
    6556     "MUL R3.xyz, R2, R1.w;\n"
    6557     "MUL R2.xyz, R1, c[7].x;\n"
    6558     "MUL R0.xyz, R0, c[6].z;\n"
    6559     "MAD R2.xyz, R2, R0.w, R3;\n"
    6560     "MUL R1.xyz, R1, c[6].y;\n"
    6561     "ADD R2.w, -R0, c[5].x;\n"
    6562     "MAD R1.xyz, R1, R2.w, R2;\n"
    6563     "ADD R2.x, -R1.w, c[5];\n"
    6564     "MAD result.color.xyz, R0, R2.x, R1;\n"
    6565     "ADD R0.y, -R0.w, c[5].x;\n"
     6472    "MUL R3.xyz, R1.w, R2;\n"
     6473    "MUL R2.xyz, R1, c[4].x;\n"
     6474    "MUL R0.xyz, R0, c[5].z;\n"
     6475    "MAD R2.xyz, R0.w, R2, R3;\n"
     6476    "ADD R2.w, -R0, c[7].x;\n"
     6477    "MUL R1.xyz, R1, c[5].y;\n"
     6478    "MAD R1.xyz, R2.w, R1, R2;\n"
     6479    "ADD R2.x, -R1.w, c[7];\n"
     6480    "MAD result.color.xyz, R2.x, R0, R1;\n"
    65666481    "MUL R0.x, R1.w, R0.w;\n"
    65676482    "MUL R0.z, R0.w, R2.x;\n"
    6568     "MUL R0.y, R1.w, R0;\n"
    6569     "DP3 result.color.w, R0, c[6];\n"
     6483    "MUL R0.y, R1.w, R2.w;\n"
     6484    "DP3 result.color.w, R0, c[5];\n"
    65706485    "END\n"
    65716486    ;
     
    65786493    "TEMP R1;\n"
    65796494    "TEMP R2;\n"
    6580     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6581     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6582     "ADD R0.xyz, R0, c[2];\n"
    6583     "RCP R0.z, R0.z;\n"
    6584     "MUL R0.zw, R0.xyxy, R0.z;\n"
    6585     "MUL R1.xy, R0.zwzw, c[3];\n"
    6586     "MOV R1.y, -R1;\n"
    6587     "MUL R0.xy, fragment.position, c[4];\n"
    6588     "TEX R0, R0, texture[0], 2D;\n"
    6589     "TEX R1.x, R1, texture[1], 2D;\n"
     6495    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6496    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6497    "ADD R0.xyz, R0, c[3];\n"
     6498    "RCP R0.z, R0.z;\n"
     6499    "MUL R0.xy, R0, R0.z;\n"
     6500    "MUL R0.xy, R0, c[0];\n"
     6501    "TEX R1.x, R0, texture[1], 2D;\n"
     6502    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6503    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6504    "ADD R1.x, -R1, c[5];\n"
    65906505    "MUL R1, fragment.color.primary, R1.x;\n"
    65916506    "ADD R2.x, -R0.w, c[5];\n"
     
    66016516static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODES_SCREEN_NOMASK =
    66026517    "!!ARBfp1.0\n"
    6603     "PARAM c[5] = { program.local[0..4] };\n"
    6604     "TEMP R0;\n"
    6605     "TEMP R1;\n"
    6606     "TEMP R2;\n"
    6607     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6608     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6609     "ADD R0.xyz, R0, c[2];\n"
    6610     "RCP R0.z, R0.z;\n"
    6611     "MUL R0.xy, R0, R0.z;\n"
    6612     "MUL R0.xy, R0, c[3];\n"
    6613     "MOV R0.w, -R0.y;\n"
    6614     "MOV R0.z, R0.x;\n"
    6615     "TEX R1.x, R0.zwzw, texture[1], 2D;\n"
    6616     "MUL R0.xy, fragment.position, c[4];\n"
    6617     "TEX R0, R0, texture[0], 2D;\n"
     6518    "PARAM c[6] = { program.local[0..4],\n"
     6519    "           { 1 } };\n"
     6520    "TEMP R0;\n"
     6521    "TEMP R1;\n"
     6522    "TEMP R2;\n"
     6523    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6524    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6525    "ADD R0.xyz, R0, c[3];\n"
     6526    "RCP R0.z, R0.z;\n"
     6527    "MUL R0.xy, R0, R0.z;\n"
     6528    "MUL R0.xy, R0, c[0];\n"
     6529    "TEX R0.x, R0, texture[1], 2D;\n"
     6530    "ADD R1.x, -R0, c[5];\n"
     6531    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6532    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    66186533    "MUL R1, fragment.color.primary, R1.x;\n"
    66196534    "ADD R2, R1, R0;\n"
     
    66256540    "!!ARBfp1.0\n"
    66266541    "PARAM c[6] = { program.local[0..4],\n"
    6627     "           { 2, 1 } };\n"
    6628     "TEMP R0;\n"
    6629     "TEMP R1;\n"
    6630     "TEMP R2;\n"
    6631     "TEMP R3;\n"
    6632     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6633     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6634     "ADD R0.xyz, R0, c[2];\n"
    6635     "RCP R0.z, R0.z;\n"
    6636     "MUL R0.xy, R0, R0.z;\n"
    6637     "MUL R0.xy, R0, c[3];\n"
    6638     "MOV R0.y, -R0;\n"
    6639     "TEX R1.x, R0, texture[1], 2D;\n"
    6640     "MUL R1, fragment.color.primary, R1.x;\n"
    6641     "MUL R0.xy, fragment.position, c[4];\n"
    6642     "TEX R0, R0, texture[0], 2D;\n"
     6542    "           { 1, 2 } };\n"
     6543    "TEMP R0;\n"
     6544    "TEMP R1;\n"
     6545    "TEMP R2;\n"
     6546    "TEMP R3;\n"
     6547    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6548    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6549    "ADD R0.xyz, R0, c[3];\n"
     6550    "RCP R0.z, R0.z;\n"
     6551    "MUL R0.xy, R0, R0.z;\n"
     6552    "MUL R0.xy, R0, c[0];\n"
     6553    "TEX R0.x, R0, texture[1], 2D;\n"
     6554    "ADD R0.x, -R0, c[5];\n"
     6555    "MUL R1, fragment.color.primary, R0.x;\n"
     6556    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6557    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    66436558    "ADD R3.xyz, R1.w, -R1;\n"
    66446559    "ADD R2.xyz, R0.w, -R0;\n"
    66456560    "MUL R2.xyz, R2, R3;\n"
    6646     "ADD R2.w, -R0, c[5].y;\n"
    6647     "MUL R2.xyz, R2, c[5].x;\n"
     6561    "ADD R2.w, -R0, c[5].x;\n"
     6562    "MUL R2.xyz, R2, c[5].y;\n"
    66486563    "MAD R2.xyz, R1.w, R0.w, -R2;\n"
    66496564    "MAD R2.xyz, R1, R2.w, R2;\n"
    66506565    "MUL R3.xyz, R1, R2.w;\n"
    66516566    "MUL R1.xyz, R1, R0;\n"
    6652     "ADD R2.w, -R1, c[5].y;\n"
    6653     "MAD R1.xyz, R1, c[5].x, R3;\n"
     6567    "ADD R2.w, -R1, c[5].x;\n"
     6568    "MAD R1.xyz, R1, c[5].y, R3;\n"
    66546569    "MAD R1.xyz, R0, R2.w, R1;\n"
    66556570    "MAD R2.xyz, R0, R2.w, R2;\n"
    6656     "MUL R0.xyz, R0, c[5].x;\n"
     6571    "MUL R0.xyz, R0, c[5].y;\n"
    66576572    "ADD R2.w, R1, R0;\n"
    66586573    "ADD R2.xyz, R2, -R1;\n"
     
    66716586    "TEMP R2;\n"
    66726587    "TEMP R3;\n"
    6673     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6674     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6675     "ADD R0.xyz, R0, c[2];\n"
    6676     "RCP R0.z, R0.z;\n"
    6677     "MUL R0.xy, R0, R0.z;\n"
    6678     "MUL R0.xy, R0, c[3];\n"
    6679     "MOV R0.y, -R0;\n"
    6680     "TEX R1.x, R0, texture[1], 2D;\n"
    6681     "MUL R0.xy, fragment.position, c[4];\n"
    6682     "TEX R0, R0, texture[0], 2D;\n"
     6588    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6589    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6590    "ADD R0.xyz, R0, c[3];\n"
     6591    "RCP R0.z, R0.z;\n"
     6592    "MUL R0.xy, R0, R0.z;\n"
     6593    "MUL R0.xy, R0, c[0];\n"
     6594    "TEX R0.x, R0, texture[1], 2D;\n"
     6595    "ADD R1.x, -R0, c[5];\n"
     6596    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6597    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    66836598    "MUL R1, fragment.color.primary, R1.x;\n"
    66846599    "MUL R2.xyz, R1, R0.w;\n"
    6685     "MUL R3.xyz, R0, R1.w;\n"
     6600    "MUL R3.xyz, R1.w, R0;\n"
    66866601    "MIN R2.xyz, R2, R3;\n"
    66876602    "ADD R2.w, -R0, c[5].x;\n"
     
    67026617    "TEMP R2;\n"
    67036618    "TEMP R3;\n"
    6704     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6705     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6706     "ADD R0.xyz, R0, c[2];\n"
    6707     "RCP R0.z, R0.z;\n"
    6708     "MUL R0.xy, R0, R0.z;\n"
    6709     "MUL R0.xy, R0, c[3];\n"
    6710     "MOV R0.y, -R0;\n"
    6711     "TEX R1.x, R0, texture[1], 2D;\n"
    6712     "MUL R0.xy, fragment.position, c[4];\n"
    6713     "TEX R0, R0, texture[0], 2D;\n"
     6619    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6620    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6621    "ADD R0.xyz, R0, c[3];\n"
     6622    "RCP R0.z, R0.z;\n"
     6623    "MUL R0.xy, R0, R0.z;\n"
     6624    "MUL R0.xy, R0, c[0];\n"
     6625    "TEX R0.x, R0, texture[1], 2D;\n"
     6626    "ADD R1.x, -R0, c[5];\n"
     6627    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6628    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    67146629    "MUL R1, fragment.color.primary, R1.x;\n"
    67156630    "MUL R2.xyz, R1, R0.w;\n"
    6716     "MUL R3.xyz, R0, R1.w;\n"
     6631    "MUL R3.xyz, R1.w, R0;\n"
    67176632    "MAX R2.xyz, R2, R3;\n"
    67186633    "ADD R2.w, -R0, c[5].x;\n"
     
    67286643    "!!ARBfp1.0\n"
    67296644    "PARAM c[6] = { program.local[0..4],\n"
    6730     "           { 1, 1e-06 } };\n"
    6731     "TEMP R0;\n"
    6732     "TEMP R1;\n"
    6733     "TEMP R2;\n"
    6734     "TEMP R3;\n"
    6735     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6736     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6737     "ADD R0.xyz, R0, c[2];\n"
    6738     "RCP R0.z, R0.z;\n"
    6739     "MUL R0.xy, R0, R0.z;\n"
    6740     "MUL R0.xy, R0, c[3];\n"
    6741     "MOV R0.y, -R0;\n"
     6645    "           { 1, 1e-006 } };\n"
     6646    "TEMP R0;\n"
     6647    "TEMP R1;\n"
     6648    "TEMP R2;\n"
     6649    "TEMP R3;\n"
     6650    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6651    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6652    "ADD R0.xyz, R0, c[3];\n"
     6653    "RCP R0.z, R0.z;\n"
     6654    "MUL R0.xy, R0, R0.z;\n"
     6655    "MUL R0.xy, R0, c[0];\n"
    67426656    "TEX R0.x, R0, texture[1], 2D;\n"
     6657    "ADD R0.x, -R0, c[5];\n"
    67436658    "MUL R1, fragment.color.primary, R0.x;\n"
    67446659    "MAX R0.x, R1.w, c[5].y;\n"
    67456660    "RCP R0.x, R0.x;\n"
    6746     "MAD R0.xyz, -R1, R0.x, c[5].x;\n"
    6747     "MAX R2.xyz, R0, c[5].y;\n"
     6661    "MAD R3.xyz, -R1, R0.x, c[5].x;\n"
     6662    "MAX R3.xyz, R3, c[5].y;\n"
    67486663    "MUL R0.xy, fragment.position, c[4];\n"
    67496664    "TEX R0, R0, texture[0], 2D;\n"
    6750     "ADD R2.w, -R1, c[5].x;\n"
    6751     "MUL R3.xyz, R0, R2.w;\n"
     6665    "ADD R2.x, -R1.w, c[5];\n"
     6666    "MUL R2.xyz, R0, R2.x;\n"
    67526667    "ADD R2.w, -R0, c[5].x;\n"
    6753     "MAD R3.xyz, R1, R2.w, R3;\n"
    6754     "MUL R0.xyz, R0, R1.w;\n"
    6755     "RCP R2.x, R2.x;\n"
    6756     "RCP R2.y, R2.y;\n"
    6757     "RCP R2.z, R2.z;\n"
    6758     "MAD R2.xyz, R0, R2, R3;\n"
     6668    "MAD R2.xyz, R1, R2.w, R2;\n"
     6669    "MUL R0.xyz, R1.w, R0;\n"
     6670    "RCP R3.x, R3.x;\n"
     6671    "RCP R3.y, R3.y;\n"
     6672    "RCP R3.z, R3.z;\n"
     6673    "MAD R3.xyz, R0, R3, R2;\n"
    67596674    "MAD R0.xyz, R1, R0.w, R0;\n"
    6760     "MAD R3.xyz, R1.w, R0.w, R3;\n"
     6675    "MAD R2.xyz, R1.w, R0.w, R2;\n"
    67616676    "MUL R2.w, R1, R0;\n"
    67626677    "ADD R1.x, R1.w, R0.w;\n"
    6763     "ADD R3.xyz, R3, -R2;\n"
     6678    "ADD R2.xyz, R2, -R3;\n"
    67646679    "SGE R0.xyz, R0, R2.w;\n"
    6765     "MAD result.color.xyz, R0, R3, R2;\n"
     6680    "MAD result.color.xyz, R0, R2, R3;\n"
    67666681    "MAD result.color.w, -R1, R0, R1.x;\n"
    67676682    "END\n"
     
    67716686    "!!ARBfp1.0\n"
    67726687    "PARAM c[6] = { program.local[0..4],\n"
    6773     "           { 1, 9.9999997e-06 } };\n"
     6688    "           { 1, 9.9999997e-006 } };\n"
    67746689    "TEMP R0;\n"
    67756690    "TEMP R1;\n"
     
    67786693    "TEMP R4;\n"
    67796694    "TEMP R5;\n"
    6780     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6781     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6782     "ADD R0.xyz, R0, c[2];\n"
    6783     "RCP R0.z, R0.z;\n"
    6784     "MUL R0.xy, R0, R0.z;\n"
    6785     "MUL R0.xy, R0, c[3];\n"
    6786     "MOV R0.y, -R0;\n"
    6787     "TEX R1.x, R0, texture[1], 2D;\n"
     6695    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6696    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6697    "ADD R0.xyz, R0, c[3];\n"
     6698    "RCP R0.z, R0.z;\n"
     6699    "MUL R0.xy, R0, R0.z;\n"
     6700    "MUL R0.xy, R0, c[0];\n"
     6701    "TEX R0.x, R0, texture[1], 2D;\n"
     6702    "ADD R1.x, -R0, c[5];\n"
    67886703    "MUL R1, fragment.color.primary, R1.x;\n"
    6789     "MUL R0.xy, fragment.position, c[4];\n"
    6790     "TEX R0, R0, texture[0], 2D;\n"
    6791     "MUL R2.xyz, R0, R1.w;\n"
     6704    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6705    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6706    "MUL R2.xyz, R1.w, R0;\n"
    67926707    "MAD R3.xyz, R1, R0.w, R2;\n"
    67936708    "ADD R2.w, -R0, c[5].x;\n"
     
    68026717    "MAD R2.xyz, R4, R2, R5;\n"
    68036718    "MUL R4.xyz, R0, R3.w;\n"
     6719    "MAD R0.xyz, R0, R3.w, R2;\n"
    68046720    "MAD R1.xyz, R1, R2.w, R4;\n"
    6805     "ADD R3.w, -R1, c[5].x;\n"
    6806     "MAD R0.xyz, R0, R3.w, R2;\n"
    68076721    "MUL R2.x, R1.w, R0.w;\n"
    68086722    "ADD R2.w, R1, R0;\n"
     
    68176731    "!!ARBfp1.0\n"
    68186732    "PARAM c[6] = { program.local[0..4],\n"
    6819     "           { 2, 1 } };\n"
     6733    "           { 1, 2 } };\n"
    68206734    "TEMP R0;\n"
    68216735    "TEMP R1;\n"
     
    68236737    "TEMP R3;\n"
    68246738    "TEMP R4;\n"
    6825     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6826     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6827     "ADD R0.xyz, R0, c[2];\n"
    6828     "RCP R0.z, R0.z;\n"
    6829     "MUL R0.xy, R0, R0.z;\n"
    6830     "MUL R0.xy, R0, c[3];\n"
    6831     "MOV R0.y, -R0;\n"
    6832     "TEX R1.x, R0, texture[1], 2D;\n"
    6833     "MUL R1, fragment.color.primary, R1.x;\n"
    6834     "MUL R0.xy, fragment.position, c[4];\n"
    6835     "TEX R0, R0, texture[0], 2D;\n"
    6836     "ADD R2.w, -R0, c[5].y;\n"
     6739    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6740    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6741    "ADD R0.xyz, R0, c[3];\n"
     6742    "RCP R0.z, R0.z;\n"
     6743    "MUL R0.xy, R0, R0.z;\n"
     6744    "MUL R0.xy, R0, c[0];\n"
     6745    "TEX R0.x, R0, texture[1], 2D;\n"
     6746    "ADD R0.x, -R0, c[5];\n"
     6747    "MUL R1, fragment.color.primary, R0.x;\n"
     6748    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6749    "TEX R0, R0.zwzw, texture[0], 2D;\n"
     6750    "ADD R2.w, -R0, c[5].x;\n"
    68376751    "ADD R3.xyz, R1.w, -R1;\n"
    68386752    "ADD R2.xyz, R0.w, -R0;\n"
    68396753    "MUL R2.xyz, R2, R3;\n"
    6840     "MUL R2.xyz, R2, c[5].x;\n"
     6754    "MUL R2.xyz, R2, c[5].y;\n"
    68416755    "MAD R2.xyz, R1.w, R0.w, -R2;\n"
     6756    "MAD R2.xyz, R1, R2.w, R2;\n"
    68426757    "MUL R4.xyz, R1, R2.w;\n"
    68436758    "MUL R3.xyz, R1, R0;\n"
    6844     "MAD R2.xyz, R1, R2.w, R2;\n"
    6845     "ADD R2.w, -R1, c[5].y;\n"
    6846     "MUL R1.xyz, R1, c[5].x;\n"
    6847     "MAD R2.xyz, R0, R2.w, R2;\n"
    6848     "MAD R3.xyz, R3, c[5].x, R4;\n"
    6849     "MAD R0.xyz, R0, R2.w, R3;\n"
    6850     "ADD R2.w, R1, R0;\n"
    6851     "ADD R2.xyz, R2, -R0;\n"
     6759    "MUL R1.xyz, R1, c[5].y;\n"
     6760    "ADD R2.w, -R1, c[5].x;\n"
     6761    "MAD R3.xyz, R3, c[5].y, R4;\n"
     6762    "MAD R3.xyz, R0, R2.w, R3;\n"
     6763    "MAD R0.xyz, R0, R2.w, R2;\n"
     6764    "ADD R2.x, R1.w, R0.w;\n"
     6765    "ADD R0.xyz, R0, -R3;\n"
    68526766    "SGE R1.xyz, R1, R1.w;\n"
    6853     "MAD result.color.xyz, R1, R2, R0;\n"
    6854     "MAD result.color.w, -R1, R0, R2;\n"
     6767    "MAD result.color.xyz, R1, R0, R3;\n"
     6768    "MAD result.color.w, -R1, R0, R2.x;\n"
    68556769    "END\n"
    68566770    ;
     
    68596773    "!!ARBfp1.0\n"
    68606774    "PARAM c[7] = { program.local[0..4],\n"
    6861     "           { 1, 9.9999997e-06, 2, 8 },\n"
    6862     "           { 3 } };\n"
     6775    "           { 1, 2, 9.9999997e-006, 4 },\n"
     6776    "           { 16, 12, 3 } };\n"
    68636777    "TEMP R0;\n"
    68646778    "TEMP R1;\n"
     
    68676781    "TEMP R4;\n"
    68686782    "TEMP R5;\n"
    6869     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6870     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6871     "ADD R1.xyz, R0, c[2];\n"
    6872     "RCP R0.z, R1.z;\n"
    6873     "MUL R1.xy, R1, R0.z;\n"
    6874     "MUL R1.xy, R1, c[3];\n"
    6875     "MOV R1.y, -R1;\n"
     6783    "TEMP R6;\n"
     6784    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6785    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6786    "ADD R1.xyz, R0, c[3];\n"
     6787    "RCP R1.z, R1.z;\n"
     6788    "MUL R1.xy, R1, R1.z;\n"
     6789    "MUL R1.xy, R1, c[0];\n"
     6790    "TEX R1.x, R1, texture[1], 2D;\n"
    68766791    "MUL R0.xy, fragment.position, c[4];\n"
    68776792    "TEX R0, R0, texture[0], 2D;\n"
    6878     "MAX R1.z, R0.w, c[5].y;\n"
    6879     "RCP R2.w, R1.z;\n"
    6880     "MUL R2.xyz, R0, R2.w;\n"
    6881     "MUL R5.xyz, -R2, c[5].w;\n"
    6882     "MAD R4.xyz, -R0, R2.w, c[5].x;\n"
    6883     "TEX R1.x, R1, texture[1], 2D;\n"
     6793    "MAX R1.z, R0.w, c[5];\n"
     6794    "RCP R1.z, R1.z;\n"
     6795    "MUL R3.xyz, R0, R1.z;\n"
     6796    "MAD R2.xyz, R3, c[6].x, -c[6].y;\n"
     6797    "ADD R1.x, -R1, c[5];\n"
    68846798    "MUL R1, fragment.color.primary, R1.x;\n"
    6885     "MAD R3.xyz, R1, c[5].z, -R1.w;\n"
    6886     "RSQ R2.x, R2.x;\n"
    6887     "RSQ R2.z, R2.z;\n"
    6888     "RSQ R2.y, R2.y;\n"
    6889     "MUL R4.xyz, R4, R3;\n"
    6890     "ADD R5.xyz, R5, c[6].x;\n"
    6891     "MUL R5.xyz, R4, R5;\n"
    6892     "ADD R4.xyz, R1.w, -R4;\n"
    6893     "RCP R2.x, R2.x;\n"
    6894     "RCP R2.z, R2.z;\n"
    6895     "RCP R2.y, R2.y;\n"
    6896     "MAD R2.xyz, R2, R0.w, -R0;\n"
    6897     "MUL R3.xyz, R2, R3;\n"
    6898     "ADD R2.xyz, R1.w, -R5;\n"
    6899     "MAD R5.xyz, R0, R1.w, R3;\n"
     6799    "MAD R4.xyz, R3, R2, c[6].z;\n"
     6800    "MAD R2.xyz, R1, c[5].y, -R1.w;\n"
     6801    "MUL R5.xyz, R0.w, R2;\n"
     6802    "MUL R6.xyz, R5, R4;\n"
     6803    "RSQ R2.w, R3.x;\n"
     6804    "RCP R4.x, R2.w;\n"
     6805    "RSQ R2.w, R3.y;\n"
     6806    "RSQ R3.w, R3.z;\n"
     6807    "RCP R4.y, R2.w;\n"
     6808    "RCP R4.z, R3.w;\n"
     6809    "ADD R4.xyz, -R3, R4;\n"
     6810    "MUL R6.xyz, R3, R6;\n"
     6811    "MUL R4.xyz, R5, R4;\n"
     6812    "ADD R3.xyz, -R3, c[5].x;\n"
     6813    "MAD R2.xyz, R2, R3, R1.w;\n"
     6814    "MUL R3.xyz, R1, c[5].y;\n"
     6815    "MAD R5.xyz, R1.w, R0, R6;\n"
     6816    "MAD R4.xyz, R1.w, R0, R4;\n"
     6817    "ADD R6.xyz, R4, -R5;\n"
     6818    "MUL R4.xyz, R0, c[5].w;\n"
     6819    "SGE R4.xyz, R4, R0.w;\n"
     6820    "MAD R4.xyz, R4, R6, R5;\n"
     6821    "MAD R4.xyz, -R0, R2, R4;\n"
    69006822    "MUL R2.xyz, R0, R2;\n"
    6901     "MUL R3.xyz, R0, c[5].w;\n"
    6902     "ADD R5.xyz, R5, -R2;\n"
    6903     "SGE R3.xyz, R3, R0.w;\n"
    6904     "MUL R3.xyz, R3, R5;\n"
    6905     "ADD R2.xyz, R2, R3;\n"
    6906     "MUL R3.xyz, R0, R4;\n"
    6907     "MUL R4.xyz, R1, c[5].z;\n"
    6908     "ADD R2.xyz, R2, -R3;\n"
    6909     "SGE R4.xyz, R4, R1.w;\n"
    6910     "MUL R2.xyz, R4, R2;\n"
    6911     "ADD R2.xyz, R3, R2;\n"
     6823    "SGE R3.xyz, R3, R1.w;\n"
     6824    "MAD R2.xyz, R3, R4, R2;\n"
    69126825    "ADD R2.w, -R0, c[5].x;\n"
    6913     "MAD R1.xyz, R1, R2.w, R2;\n"
    6914     "ADD R2.x, R1.w, R0.w;\n"
    6915     "ADD R2.y, -R1.w, c[5].x;\n"
    6916     "MAD result.color.xyz, R0, R2.y, R1;\n"
    6917     "MAD result.color.w, -R1, R0, R2.x;\n"
     6826    "MAD R2.xyz, R1, R2.w, R2;\n"
     6827    "ADD R1.x, R1.w, R0.w;\n"
     6828    "ADD R1.y, -R1.w, c[5].x;\n"
     6829    "MAD result.color.xyz, R0, R1.y, R2;\n"
     6830    "MAD result.color.w, -R1, R0, R1.x;\n"
    69186831    "END\n"
    69196832    ;
     
    69226835    "!!ARBfp1.0\n"
    69236836    "PARAM c[6] = { program.local[0..4],\n"
    6924     "           { 2 } };\n"
    6925     "TEMP R0;\n"
    6926     "TEMP R1;\n"
    6927     "TEMP R2;\n"
    6928     "TEMP R3;\n"
    6929     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6930     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6931     "ADD R0.xyz, R0, c[2];\n"
    6932     "RCP R0.z, R0.z;\n"
    6933     "MUL R0.xy, R0, R0.z;\n"
    6934     "MUL R0.xy, R0, c[3];\n"
    6935     "MOV R0.y, -R0;\n"
    6936     "TEX R1.x, R0, texture[1], 2D;\n"
    6937     "MUL R0.xy, fragment.position, c[4];\n"
     6837    "           { 1, 2 } };\n"
     6838    "TEMP R0;\n"
     6839    "TEMP R1;\n"
     6840    "TEMP R2;\n"
     6841    "TEMP R3;\n"
     6842    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6843    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6844    "ADD R0.xyz, R0, c[3];\n"
     6845    "RCP R0.z, R0.z;\n"
     6846    "MUL R0.xy, R0, R0.z;\n"
     6847    "MUL R0.xy, R0, c[0];\n"
     6848    "TEX R0.x, R0, texture[1], 2D;\n"
     6849    "ADD R1.x, -R0, c[5];\n"
     6850    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6851    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    69386852    "MUL R1, fragment.color.primary, R1.x;\n"
    6939     "TEX R0, R0, texture[0], 2D;\n"
    6940     "MUL R3.xyz, R0, R1.w;\n"
     6853    "MUL R3.xyz, R1.w, R0;\n"
    69416854    "MUL R2.xyz, R1, R0.w;\n"
    69426855    "ADD R0.xyz, R1, R0;\n"
    69436856    "MIN R2.xyz, R2, R3;\n"
    69446857    "ADD R1.x, R1.w, R0.w;\n"
    6945     "MAD result.color.xyz, -R2, c[5].x, R0;\n"
     6858    "MAD result.color.xyz, -R2, c[5].y, R0;\n"
    69466859    "MAD result.color.w, -R1, R0, R1.x;\n"
    69476860    "END\n"
     
    69566869    "TEMP R2;\n"
    69576870    "TEMP R3;\n"
    6958     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6959     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6960     "ADD R0.xyz, R0, c[2];\n"
    6961     "RCP R0.z, R0.z;\n"
    6962     "MUL R0.xy, R0, R0.z;\n"
    6963     "MUL R0.xy, R0, c[3];\n"
    6964     "MOV R0.y, -R0;\n"
    6965     "TEX R1.x, R0, texture[1], 2D;\n"
    6966     "MUL R0.xy, fragment.position, c[4];\n"
    6967     "TEX R0, R0, texture[0], 2D;\n"
     6871    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6872    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6873    "ADD R0.xyz, R0, c[3];\n"
     6874    "RCP R0.z, R0.z;\n"
     6875    "MUL R0.xy, R0, R0.z;\n"
     6876    "MUL R0.xy, R0, c[0];\n"
     6877    "TEX R0.x, R0, texture[1], 2D;\n"
     6878    "ADD R1.x, -R0, c[5];\n"
     6879    "MUL R0.zw, fragment.position.xyxy, c[4].xyxy;\n"
     6880    "TEX R0, R0.zwzw, texture[0], 2D;\n"
    69686881    "MUL R1, fragment.color.primary, R1.x;\n"
    6969     "MUL R2.xyz, R0, R1.w;\n"
     6882    "MUL R2.xyz, R1.w, R0;\n"
    69706883    "MAD R3.xyz, R1, R0.w, R2;\n"
    69716884    "MUL R2.xyz, R1, R0;\n"
     
    69826895static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_MASK =
    69836896    "!!ARBfp1.0\n"
    6984     "PARAM c[7] = { program.local[0..6] };\n"
    6985     "TEMP R0;\n"
    6986     "TEMP R1;\n"
    6987     "MUL R0.xyz, fragment.position.y, c[1];\n"
    6988     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    6989     "ADD R1.xyz, R0, c[2];\n"
    6990     "RCP R0.z, R1.z;\n"
    6991     "MUL R0.zw, R1.xyxy, R0.z;\n"
    6992     "MUL R1.xy, R0.zwzw, c[3];\n"
    6993     "MOV R1.y, -R1;\n"
    6994     "ADD R0.xy, fragment.position, c[4];\n"
    6995     "MUL R0.xy, R0, c[5];\n"
     6897    "PARAM c[8] = { program.local[0..6],\n"
     6898    "           { 1 } };\n"
     6899    "TEMP R0;\n"
     6900    "TEMP R1;\n"
     6901    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6902    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6903    "ADD R0.xyz, R0, c[3];\n"
     6904    "RCP R0.z, R0.z;\n"
     6905    "MUL R0.zw, R0.xyxy, R0.z;\n"
     6906    "MUL R0.zw, R0, c[0].xyxy;\n"
     6907    "TEX R1.x, R0.zwzw, texture[1], 2D;\n"
     6908    "ADD R0.xy, fragment.position, c[5];\n"
     6909    "MUL R0.xy, R0, c[4];\n"
    69966910    "TEX R0, R0, texture[0], 2D;\n"
    6997     "TEX R1.x, R1, texture[1], 2D;\n"
    6998     "DP4 R0.x, R0, c[6];\n"
    6999     "MUL R1, fragment.color.primary, R1.x;\n"
    7000     "MUL result.color, R1, R0.x;\n"
     6911    "DP4 R1.y, R0, c[6];\n"
     6912    "ADD R1.x, -R1, c[7];\n"
     6913    "MUL R0, fragment.color.primary, R1.x;\n"
     6914    "MUL result.color, R0, R1.y;\n"
    70016915    "END\n"
    70026916    ;
     
    70046918static const char *FragmentProgram_FRAGMENT_PROGRAM_BRUSH_PATTERN_COMPOSITION_MODE_BLEND_MODE_NOMASK =
    70056919    "!!ARBfp1.0\n"
    7006     "PARAM c[4] = { program.local[0..3] };\n"
    7007     "TEMP R0;\n"
    7008     "MUL R0.xyz, fragment.position.y, c[1];\n"
    7009     "MAD R0.xyz, fragment.position.x, c[0], R0;\n"
    7010     "ADD R0.xyz, R0, c[2];\n"
    7011     "RCP R0.z, R0.z;\n"
    7012     "MUL R0.xy, R0, R0.z;\n"
    7013     "MUL R0.xy, R0, c[3];\n"
    7014     "MOV R0.y, -R0;\n"
     6920    "PARAM c[5] = { program.local[0..3],\n"
     6921    "           { 1 } };\n"
     6922    "TEMP R0;\n"
     6923    "MUL R0.xyz, fragment.position.y, c[2];\n"
     6924    "MAD R0.xyz, fragment.position.x, c[1], R0;\n"
     6925    "ADD R0.xyz, R0, c[3];\n"
     6926    "RCP R0.z, R0.z;\n"
     6927    "MUL R0.xy, R0, R0.z;\n"
     6928    "MUL R0.xy, R0, c[0];\n"
    70156929    "TEX R0.x, R0, texture[0], 2D;\n"
     6930    "ADD R0.x, -R0, c[4];\n"
    70166931    "MUL result.color, fragment.color.primary, R0.x;\n"
    70176932    "END\n"
     
    71967111static int painter_variable_locations[num_fragment_brushes][num_fragment_composition_modes][num_fragment_variables] = {
    71977112    {
    7198         { -1, -1, -1, 1, -1, 6, 2, -1, 5, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7199         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7200         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7201         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7202         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7203         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7204         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7205         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7206         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7207         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7208         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7209         { -1, -1, -1, 1, -1, -1, 2, -1, -1, 3, 1, 0, -1, 0, -1, -1, -1, -1, -1, },
    7210         { -1, -1, -1, -1, -1, 3, -1, -1, 2, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
     7113        { -1, -1, -1, 2, -1, 0, 5, -1, 1, 3, 1, 0, -1, 4, -1, -1, -1, -1, -1, },
     7114        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7115        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7116        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7117        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7118        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7119        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7120        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7121        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7122        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7123        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7124        { -1, -1, -1, 0, -1, -1, 3, -1, -1, 1, 1, 0, -1, 2, -1, -1, -1, -1, -1, },
     7125        { -1, -1, -1, -1, -1, 0, -1, -1, 1, 2, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
    72117126        { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
    72127127        { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
     
    72207135        { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
    72217136        { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, -1, },
    7222         { -1, -1, -1, 1, -1, -1, 2, -1, -1, -1, 0, -1, -1, 0, -1, -1, -1, -1, -1, },
     7137        { -1, -1, -1, 0, -1, -1, 2, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1, -1, -1, },
    72237138        { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
    72247139    },
    72257140    {
    7226         { -1, -1, 4, 1, 5, 11, 2, -1, 10, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7227         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7228         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7229         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7230         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7231         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7232         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7233         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7234         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7235         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7236         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7237         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 9, 1, 0, 2, 0, -1, 8, 6, 3, -1, },
    7238         { -1, -1, 1, -1, 2, 8, -1, -1, 7, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7239         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7240         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7241         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7242         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7243         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7244         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7245         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7246         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7247         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7248         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7249         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 6, -1, 0, 1, -1, -1, 5, 3, 0, -1, },
    7250         { -1, -1, 1, 7, 2, -1, 8, -1, -1, -1, 0, -1, 1, 6, -1, 5, 3, 0, -1, },
    7251         { -1, -1, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 5, 3, 0, -1, },
     7141        { -1, -1, 3, 7, 4, 5, 10, -1, 6, 8, 1, 0, 2, 9, -1, 1, 0, 2, -1, },
     7142        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7143        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7144        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7145        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7146        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7147        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7148        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7149        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7150        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7151        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7152        { -1, -1, 3, 5, 4, -1, 8, -1, -1, 6, 1, 0, 2, 7, -1, 1, 0, 2, -1, },
     7153        { -1, -1, 3, -1, 4, 5, -1, -1, 6, 7, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7154        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7155        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7156        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7157        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7158        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7159        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7160        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7161        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7162        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7163        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7164        { -1, -1, 3, -1, 4, -1, -1, -1, -1, 5, -1, 0, 1, -1, -1, 1, 0, 2, -1, },
     7165        { -1, -1, 3, 5, 4, -1, 7, -1, -1, -1, 0, -1, 1, 6, -1, 1, 0, 2, -1, },
     7166        { -1, -1, 3, -1, 4, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, 0, 2, -1, },
    72527167    },
    72537168    {
    7254         { -1, -1, 4, 1, 5, 12, 2, -1, 11, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7255         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7256         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7257         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7258         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7259         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7260         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7261         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7262         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7263         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7264         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7265         { -1, -1, 4, 1, 5, -1, 2, -1, -1, 10, 1, 0, 2, 0, -1, -1, -1, 3, 8, },
    7266         { -1, -1, 1, -1, 2, 9, -1, -1, 8, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7267         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7268         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7269         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7270         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7271         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7272         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7273         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7274         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7275         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7276         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7277         { -1, -1, 1, -1, 2, -1, -1, -1, -1, 7, -1, 0, 1, -1, -1, -1, -1, 0, 5, },
    7278         { -1, -1, 1, 8, 2, -1, 9, -1, -1, -1, 0, -1, 1, 7, -1, -1, -1, 0, 5, },
    7279         { -1, -1, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 0, 5, },
     7169        { -1, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, 2, 8, -1, -1, -1, 1, 0, },
     7170        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7171        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7172        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7173        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7174        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7175        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7176        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7177        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7178        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7179        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7180        { -1, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, 0, },
     7181        { -1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7182        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7183        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7184        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7185        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7186        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7187        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7188        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7189        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7190        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7191        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7192        { -1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, 0, },
     7193        { -1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, 1, 5, -1, -1, -1, 1, 0, },
     7194        { -1, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, 0, },
    72807195    },
    72817196    {
    7282         { -1, 6, 4, 1, 5, 10, 2, -1, 9, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7283         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7284         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7285         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7286         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7287         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7288         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7289         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7290         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7291         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7292         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7293         { -1, 6, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, 2, 0, -1, -1, -1, 3, -1, },
    7294         { -1, 3, 1, -1, 2, 7, -1, -1, 6, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7295         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7296         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7297         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7298         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7299         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7300         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7301         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7302         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7303         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7304         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7305         { -1, 3, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 0, -1, },
    7306         { -1, 3, 1, 5, 2, -1, 6, -1, -1, -1, 0, -1, 1, 4, -1, -1, -1, 0, -1, },
    7307         { -1, 3, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 0, -1, },
     7197        { -1, 0, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, 2, 8, -1, -1, -1, 1, -1, },
     7198        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7199        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7200        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7201        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7202        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7203        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7204        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7205        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7206        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7207        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7208        { -1, 0, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, 2, 6, -1, -1, -1, 1, -1, },
     7209        { -1, 0, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7210        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7211        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7212        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7213        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7214        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7215        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7216        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7217        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7218        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7219        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7220        { -1, 0, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, 1, -1, -1, -1, -1, 1, -1, },
     7221        { -1, 0, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, 1, 5, -1, -1, -1, 1, -1, },
     7222        { -1, 0, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, -1, },
    73087223    },
    73097224    {
    7310         { 2, -1, 4, 1, 5, 10, 2, -1, 9, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7311         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7312         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7313         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7314         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7315         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7316         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7317         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7318         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7319         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7320         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7321         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7322         { 1, -1, 1, -1, 2, 7, -1, -1, 6, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7323         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7324         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7325         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7326         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7327         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7328         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7329         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7330         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7331         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7332         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7333         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7334         { 1, -1, 1, 5, 2, -1, 6, -1, -1, -1, 0, -1, -1, 4, 3, -1, -1, 0, -1, },
    7335         { 0, -1, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, },
     7225        { 2, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, -1, 8, 0, -1, -1, 1, -1, },
     7226        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7227        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7228        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7229        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7230        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7231        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7232        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7233        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7234        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7235        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7236        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7237        { 1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7238        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7239        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7240        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7241        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7242        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7243        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7244        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7245        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7246        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7247        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7248        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7249        { 1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, -1, 5, 0, -1, -1, 1, -1, },
     7250        { 0, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, },
    73367251    },
    73377252    {
    7338         { 2, -1, 4, 1, 5, 10, 2, -1, 9, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7339         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7340         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7341         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7342         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7343         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7344         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7345         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7346         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7347         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7348         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7349         { 2, -1, 4, 1, 5, -1, 2, -1, -1, 7, 1, 0, -1, 0, 6, -1, -1, 3, -1, },
    7350         { 1, -1, 1, -1, 2, 7, -1, -1, 6, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7351         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7352         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7353         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7354         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7355         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7356         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7357         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7358         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7359         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7360         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7361         { 1, -1, 1, -1, 2, -1, -1, -1, -1, 4, -1, 0, -1, -1, 3, -1, -1, 0, -1, },
    7362         { 1, -1, 1, 5, 2, -1, 6, -1, -1, -1, 0, -1, -1, 4, 3, -1, -1, 0, -1, },
    7363         { 0, -1, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, },
     7253        { 2, -1, 2, 6, 3, 4, 9, -1, 5, 7, 1, 0, -1, 8, 0, -1, -1, 1, -1, },
     7254        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7255        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7256        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7257        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7258        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7259        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7260        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7261        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7262        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7263        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7264        { 2, -1, 2, 4, 3, -1, 7, -1, -1, 5, 1, 0, -1, 6, 0, -1, -1, 1, -1, },
     7265        { 1, -1, 2, -1, 3, 4, -1, -1, 5, 6, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7266        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7267        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7268        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7269        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7270        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7271        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7272        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7273        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7274        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7275        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7276        { 1, -1, 2, -1, 3, -1, -1, -1, -1, 4, -1, 0, -1, -1, 0, -1, -1, 1, -1, },
     7277        { 1, -1, 2, 4, 3, -1, 6, -1, -1, -1, 0, -1, -1, 5, 0, -1, -1, 1, -1, },
     7278        { 0, -1, 2, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, },
    73647279    },
    73657280};
     
    73677282static int mask_variable_locations[num_fragment_masks][num_fragment_variables] = {
    73687283    { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
    7369     { -1, -1, 2, -1, 3, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, },
     7284    { -1, -1, 1, -1, 2, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, },
    73707285};
    73717286
  • trunk/src/opengl/util/generator.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtOpenGL module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     24** In addition, as a special exception, Nokia gives you certain additional
     25** rights.  These rights are described in the Nokia Qt LGPL Exception
     26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4949
    5050#include <QtDebug>
     51#include <cstdlib>
    5152
    5253QT_BEGIN_NAMESPACE
    5354
    5455QT_USE_NAMESPACE
     56
     57#define TAB "    "
    5558
    5659typedef QPair<QString, QString> QStringPair;
     
    117120
    118121        if (lineStream.atEnd()) {
    119             qDebug() << "Error in file" << confFile << "(" << enumerator << ")";
     122            qDebug() << "Error in file" << confFile << '(' << enumerator << ')';
    120123            exit(0);
    121124        }
     
    243246}
    244247
     248void writeVariablesEnum(QTextStream &out, const char *name, const QSet<QString> &s)
     249{
     250    out << "enum " << name << " {";
     251    QSet<QString>::const_iterator it = s.begin();
     252    if (it != s.end()) {
     253        out << "\n" TAB "VAR_" << it->toUpper();
     254        for (++it; it != s.end(); ++it)
     255            out << ",\n" TAB "VAR_" << it->toUpper();
     256    }
     257    out << "\n};\n\n";
     258}
     259
     260void writeTypesEnum(QTextStream &out, const char *name, const QList<QStringPair> &s)
     261{
     262    out << "enum " << name << " {";
     263    QList<QStringPair>::const_iterator it = s.begin();
     264    if (it != s.end()) {
     265        out << "\n" TAB << it->first;
     266        for (++it; it != s.end(); ++it)
     267            out << ",\n" TAB << it->first;
     268    }
     269    out << "\n};\n\n";
     270}
     271
    245272void writeIncludeFile(const QSet<QString> &variables,
    246273                      const QList<QStringPair> &brushes,
     
    257284    QTextStream out(&includeFile);
    258285
    259     QLatin1String tab("    ");
    260 
    261     out << "#ifndef FRAGMENTPROGRAMS_H\n"
    262         << "#define FRAGMENTPROGRAMS_H\n\n";
    263 
    264     out << "enum FragmentVariable {\n";
    265     foreach (QString str, variables)
    266         out << tab << "VAR_" << str.toUpper() << ",\n";
    267     out << "};\n\n";
    268 
    269     out << "enum FragmentBrushType {\n";
    270     foreach (QStringPair brush, brushes)
    271         out << tab << brush.first << ",\n";
    272     out << "};\n\n";
    273 
    274     out << "enum FragmentCompositionModeType {\n";
    275     foreach (QStringPair mode, compositionModes)
    276         out << tab << mode.first << ",\n";
    277     out << "};\n\n";
    278 
    279     out << "enum FragmentMaskType {\n";
    280     foreach (QStringPair mask, masks)
    281         out << tab << mask.first << ",\n";
    282     out << "};\n\n";
     286    QLatin1String tab(TAB);
     287
     288    out << "/****************************************************************************\n"
     289           "**\n"
     290           "** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).\n"
     291           "** All rights reserved.\n"
     292           "** Contact: Nokia Corporation (qt-info@nokia.com)\n"
     293           "**\n"
     294           "** This file is part of the QtOpenGL module of the Qt Toolkit.\n"
     295           "**\n"
     296           "** $QT_BEGIN_LICENSE:LGPL$\n"
     297           "** Commercial Usage\n"
     298           "** Licensees holding valid Qt Commercial licenses may use this file in\n"
     299           "** accordance with the Qt Commercial License Agreement provided with the\n"
     300           "** Software or, alternatively, in accordance with the terms contained in\n"
     301           "** a written agreement between you and Nokia.\n"
     302           "**\n"
     303           "** GNU Lesser General Public License Usage\n"
     304           "** Alternatively, this file may be used under the terms of the GNU Lesser\n"
     305           "** General Public License version 2.1 as published by the Free Software\n"
     306           "** Foundation and appearing in the file LICENSE.LGPL included in the\n"
     307           "** packaging of this file.  Please review the following information to\n"
     308           "** ensure the GNU Lesser General Public License version 2.1 requirements\n"
     309           "** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n"
     310           "**\n"
     311           "** In addition, as a special exception, Nokia gives you certain additional\n"
     312           "** rights.  These rights are described in the Nokia Qt LGPL Exception\n"
     313           "** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n"
     314           "**\n"
     315           "** GNU General Public License Usage\n"
     316           "** Alternatively, this file may be used under the terms of the GNU\n"
     317           "** General Public License version 3.0 as published by the Free Software\n"
     318           "** Foundation and appearing in the file LICENSE.GPL included in the\n"
     319           "** packaging of this file.  Please review the following information to\n"
     320           "** ensure the GNU General Public License version 3.0 requirements will be\n"
     321           "** met: http://www.gnu.org/copyleft/gpl.html.\n"
     322           "**\n"
     323           "** If you have questions regarding the use of this file, please contact\n"
     324           "** Nokia at qt-info@nokia.com.\n"
     325           "** $QT_END_LICENSE$\n"
     326           "**\n"
     327           "****************************************************************************/\n"
     328           "\n"
     329           "#ifndef FRAGMENTPROGRAMS_P_H\n"
     330           "#define FRAGMENTPROGRAMS_P_H\n"
     331           "\n"
     332           "//\n"
     333           "//  W A R N I N G\n"
     334           "//  -------------\n"
     335           "//\n"
     336           "// This file is not part of the Qt API.  It exists purely as an\n"
     337           "// implementation detail.  This header file may change from version to\n"
     338           "// version without notice, or even be removed.\n"
     339           "//\n"
     340           "// We mean it.\n"
     341           "//\n"
     342           "\n";
     343
     344    writeVariablesEnum(out, "FragmentVariable", variables);
     345    writeTypesEnum(out, "FragmentBrushType", brushes);
     346    writeTypesEnum(out, "FragmentCompositionModeType", compositionModes);
     347    writeTypesEnum(out, "FragmentMaskType", masks);
    283348
    284349    out << "static const unsigned int num_fragment_variables = " << variables.size() << ";\n\n";
  • trunk/src/opengl/util/generator.pro

    r2 r561  
    1010# Input
    1111SOURCES += generator.cpp
     12
     13CONFIG += console
  • trunk/src/opengl/util/glsl_to_include.sh

    r2 r561  
    11#! /bin/sh
     2#############################################################################
     3##
     4## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     5## All rights reserved.
     6## Contact: Nokia Corporation (qt-info@nokia.com)
     7##
     8## This file is the build configuration utility of the Qt Toolkit.
     9##
     10## $QT_BEGIN_LICENSE:LGPL$
     11## Commercial Usage
     12## Licensees holding valid Qt Commercial licenses may use this file in
     13## accordance with the Qt Commercial License Agreement provided with the
     14## Software or, alternatively, in accordance with the terms contained in
     15## a written agreement between you and Nokia.
     16##
     17## GNU Lesser General Public License Usage
     18## Alternatively, this file may be used under the terms of the GNU Lesser
     19## General Public License version 2.1 as published by the Free Software
     20## Foundation and appearing in the file LICENSE.LGPL included in the
     21## packaging of this file.  Please review the following information to
     22## ensure the GNU Lesser General Public License version 2.1 requirements
     23## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
     24##
     25## In addition, as a special exception, Nokia gives you certain additional
     26## rights.  These rights are described in the Nokia Qt LGPL Exception
     27## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
     28##
     29## GNU General Public License Usage
     30## Alternatively, this file may be used under the terms of the GNU
     31## General Public License version 3.0 as published by the Free Software
     32## Foundation and appearing in the file LICENSE.GPL included in the
     33## packaging of this file.  Please review the following information to
     34## ensure the GNU General Public License version 3.0 requirements will be
     35## met: http://www.gnu.org/copyleft/gpl.html.
     36##
     37## If you have questions regarding the use of this file, please contact
     38## Nokia at qt-info@nokia.com.
     39## $QT_END_LICENSE$
     40##
     41#############################################################################
    242
    343# Compile a .glsl file to a file that can be included in a C++ program
  • trunk/src/opengl/util/masks.conf

    r2 r561  
    11FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA trap_exact_aa.glsl
    22FRAGMENT_PROGRAM_MASK_ELLIPSE_AA ellipse_aa.glsl
    3 #FRAGMENT_PROGRAM_MASK_ELLIPSE ellipse.glsl
  • trunk/src/opengl/util/pattern_brush.glsl

    r2 r561  
    1818    coords *= inv_brush_texture_size;
    1919
    20     coords.y = -coords.y;
    21 
    22     float alpha = texture2D(brush_texture, coords).r;
     20    float alpha = 1.0 - texture2D(brush_texture, coords).r;
    2321
    2422    return gl_Color * alpha;
  • trunk/src/opengl/util/simple_porter_duff.glsl

    r2 r561  
    88    result.xyz = porterduff_ab.x * src.xyz * dst.a
    99               + porterduff_ab.y * dst.xyz * src.a
    10                + porterduff_xyz.y * src.xyz * (1 - dst.a)
    11                + porterduff_xyz.z * dst.xyz * (1 - src.a);
     10               + porterduff_xyz.y * src.xyz * (1.0 - dst.a)
     11               + porterduff_xyz.z * dst.xyz * (1.0 - src.a);
    1212
    13     result.a = dot(porterduff_xyz, vec3(src.a * dst.a, src.a * (1 - dst.a), dst.a * (1 - src.a)));
     13    result.a = dot(porterduff_xyz, vec3(src.a * dst.a, src.a * (1.0 - dst.a), dst.a * (1.0 - src.a)));
    1414
    1515    return result;
  • trunk/src/opengl/util/texture_brush.glsl

    r2 r561  
    1818    coords *= inv_brush_texture_size;
    1919
    20     coords.y = -coords.y;
    21 
    2220    return texture2D(brush_texture, coords);
    2321}
  • trunk/src/opengl/util/trap_exact_aa.glsl

    r2 r561  
    1515
    1616    // transform right line to left to be able to use same calculations for both
    17     vecX.zw = 2 * gl_FragCoord.x - vecX.zw;
     17    vecX.zw = 2.0 * gl_FragCoord.x - vecX.zw;
    1818
    1919    vec2 topX = vec2(vecX.x, vecX.z);
     
    3434    vec2 temp = mix(area - 0.5 * (right - bottomXTemp) * (intersectY.yw - bottom), // left < bottom < right < top
    3535                    (0.5 * (topXTemp + bottomXTemp) - left) * area,    // left < bottom < top < right
    36                     step(topXTemp, right));
     36                    step(topXTemp, right.xx));
    3737
    3838    vec2 excluded = 0.5 * (top - intersectY.xz) * (topXTemp - left); // bottom < left < top < right
    3939
    4040    excluded = mix((top - 0.5 * (intersectY.yw + intersectY.xz)) * (right - left), // bottom < left < right < top
    41                    excluded, step(topXTemp, right));
     41                   excluded, step(topXTemp, right.xx));
    4242
    4343    excluded = mix(temp, // left < bottom < right (see calculation of temp)
    44                    excluded, step(bottomXTemp, left));
     44                   excluded, step(bottomXTemp, left.xx));
    4545
    4646    excluded = mix(vec2(area, area), // right < bottom < top
    47                    excluded, step(bottomXTemp, right));
     47                   excluded, step(bottomXTemp, right.xx));
    4848
    4949    excluded *= step(left, topXTemp);
     
    5454void main()
    5555{
    56     gl_FragColor = quad_aa();
     56    gl_FragColor = quad_aa().xxxx;
    5757}
    5858
Note: See TracChangeset for help on using the changeset viewer.