src/opengl/qpaintengine_opengl.cpp
changeset 30 5dc02b23752f
parent 25 e24348a560a6
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    58 #include "qvarlengtharray.h"
    58 #include "qvarlengtharray.h"
    59 #include <private/qpainter_p.h>
    59 #include <private/qpainter_p.h>
    60 #include <private/qglpixelbuffer_p.h>
    60 #include <private/qglpixelbuffer_p.h>
    61 #include <private/qbezier_p.h>
    61 #include <private/qbezier_p.h>
    62 #include <qglframebufferobject.h>
    62 #include <qglframebufferobject.h>
       
    63 #include <private/qstatictext_p.h>
    63 
    64 
    64 #include "private/qtessellator_p.h"
    65 #include "private/qtessellator_p.h"
    65 
    66 
    66 #include "util/fragmentprograms_p.h"
    67 #include "util/fragmentprograms_p.h"
    67 
    68 
    68 #ifdef Q_WS_QWS
    69 #ifdef Q_WS_QWS
    69 #include "private/qglwindowsurface_qws_p.h"
    70 #include "private/qglwindowsurface_qws_p.h"
    70 #include "qwsmanager_qws.h"
    71 #include "qwsmanager_qws.h"
    71 #include "private/qwsmanager_p.h"
    72 #include "private/qwsmanager_p.h"
    72 #endif
       
    73 
       
    74 #ifdef QT_OPENGL_ES_1_CL
       
    75 #include "qgl_cl_p.h"
       
    76 #endif
    73 #endif
    77 
    74 
    78 #define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context());
    75 #define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context());
    79 
    76 
    80 #include <stdlib.h>
    77 #include <stdlib.h>
   669         , inverseScale(1)
   666         , inverseScale(1)
   670         , moveToCount(0)
   667         , moveToCount(0)
   671         , last_created_state(0)
   668         , last_created_state(0)
   672         , shader_ctx(0)
   669         , shader_ctx(0)
   673         , grad_palette(0)
   670         , grad_palette(0)
       
   671         , tess_points(0)
   674         , drawable_texture(0)
   672         , drawable_texture(0)
   675         , ref_cleaner(this)
   673         , ref_cleaner(this)
   676         {}
   674         {}
   677 
   675 
   678     inline void setGLPen(const QColor &c) {
   676     inline void setGLPen(const QColor &c) {
   778     void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset);
   776     void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset);
   779 
   777 
   780     void drawOffscreenPath(const QPainterPath &path);
   778     void drawOffscreenPath(const QPainterPath &path);
   781 
   779 
   782     void composite(const QRectF &rect, const QPoint &maskOffset = QPoint());
   780     void composite(const QRectF &rect, const QPoint &maskOffset = QPoint());
   783     void composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint());
   781     void composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint());
   784 
   782 
   785     bool createFragmentPrograms();
   783     bool createFragmentPrograms();
   786     void deleteFragmentPrograms();
   784     void deleteFragmentPrograms();
   787     void updateFragmentProgramData(int locations[]);
   785     void updateFragmentProgramData(int locations[]);
   788 
   786 
  1790 class QOpenGLTrapezoidToArrayTessellator : public QOpenGLTessellator
  1788 class QOpenGLTrapezoidToArrayTessellator : public QOpenGLTessellator
  1791 {
  1789 {
  1792 public:
  1790 public:
  1793     QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {}
  1791     QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {}
  1794     ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); }
  1792     ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); }
  1795     q_vertexType *vertices;
  1793     GLfloat *vertices;
  1796     int allocated;
  1794     int allocated;
  1797     int size;
  1795     int size;
  1798     QRectF bounds;
  1796     QRectF bounds;
  1799     void addTrap(const Trapezoid &trap);
  1797     void addTrap(const Trapezoid &trap);
  1800     void tessellate(const QPointF *points, int nPoints, bool winding) {
  1798     void tessellate(const QPointF *points, int nPoints, bool winding) {
  1811     if (size > allocated - 8) {
  1809     if (size > allocated - 8) {
  1812 #else
  1810 #else
  1813     if (size > allocated - 12) {
  1811     if (size > allocated - 12) {
  1814 #endif
  1812 #endif
  1815         allocated = qMax(2*allocated, 512);
  1813         allocated = qMax(2*allocated, 512);
  1816         vertices = (q_vertexType *)realloc(vertices, allocated * sizeof(q_vertexType));
  1814         vertices = (GLfloat *)realloc(vertices, allocated * sizeof(GLfloat));
  1817     }
  1815     }
  1818 
  1816 
  1819     QGLTrapezoid t = toGLTrapezoid(trap);
  1817     QGLTrapezoid t = toGLTrapezoid(trap);
  1820 
  1818 
  1821 #ifndef QT_OPENGL_ES
  1819 #ifndef QT_OPENGL_ES
  1822     vertices[size++] = f2vt(t.topLeftX);
  1820     vertices[size++] = t.topLeftX;
  1823     vertices[size++] = f2vt(t.top);
  1821     vertices[size++] = t.top;
  1824     vertices[size++] = f2vt(t.topRightX);
  1822     vertices[size++] = t.topRightX;
  1825     vertices[size++] = f2vt(t.top);
  1823     vertices[size++] = t.top;
  1826     vertices[size++] = f2vt(t.bottomRightX);
  1824     vertices[size++] = t.bottomRightX;
  1827     vertices[size++] = f2vt(t.bottom);
  1825     vertices[size++] = t.bottom;
  1828     vertices[size++] = f2vt(t.bottomLeftX);
  1826     vertices[size++] = t.bottomLeftX;
  1829     vertices[size++] = f2vt(t.bottom);
  1827     vertices[size++] = t.bottom;
  1830 #else
  1828 #else
  1831     // First triangle
  1829     // First triangle
  1832     vertices[size++] = f2vt(t.topLeftX);
  1830     vertices[size++] = t.topLeftX;
  1833     vertices[size++] = f2vt(t.top);
  1831     vertices[size++] = t.top;
  1834     vertices[size++] = f2vt(t.topRightX);
  1832     vertices[size++] = t.topRightX;
  1835     vertices[size++] = f2vt(t.top);
  1833     vertices[size++] = t.top;
  1836     vertices[size++] = f2vt(t.bottomRightX);
  1834     vertices[size++] = t.bottomRightX;
  1837     vertices[size++] = f2vt(t.bottom);
  1835     vertices[size++] = t.bottom;
  1838 
  1836 
  1839     // Second triangle
  1837     // Second triangle
  1840     vertices[size++] = f2vt(t.bottomLeftX);
  1838     vertices[size++] = t.bottomLeftX;
  1841     vertices[size++] = f2vt(t.bottom);
  1839     vertices[size++] = t.bottom;
  1842     vertices[size++] = f2vt(t.topLeftX);
  1840     vertices[size++] = t.topLeftX;
  1843     vertices[size++] = f2vt(t.top);
  1841     vertices[size++] = t.top;
  1844     vertices[size++] = f2vt(t.bottomRightX);
  1842     vertices[size++] = t.bottomRightX;
  1845     vertices[size++] = f2vt(t.bottom);
  1843     vertices[size++] = t.bottom;
  1846 #endif
  1844 #endif
  1847 }
  1845 }
  1848 
  1846 
  1849 
  1847 
  1850 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
  1848 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
  1867 #endif
  1865 #endif
  1868 
  1866 
  1869     if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) {
  1867     if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) {
  1870         composite(geometry_mode, tessellator.vertices, tessellator.size / 2);
  1868         composite(geometry_mode, tessellator.vertices, tessellator.size / 2);
  1871     } else {
  1869     } else {
  1872         glVertexPointer(2, q_vertexTypeEnum, 0, tessellator.vertices);
  1870         glVertexPointer(2, GL_FLOAT, 0, tessellator.vertices);
  1873         glEnableClientState(GL_VERTEX_ARRAY);
  1871         glEnableClientState(GL_VERTEX_ARRAY);
  1874         glDrawArrays(geometry_mode, 0, tessellator.size/2);
  1872         glDrawArrays(geometry_mode, 0, tessellator.size/2);
  1875         glDisableClientState(GL_VERTEX_ARRAY);
  1873         glDisableClientState(GL_VERTEX_ARRAY);
  1876     }
  1874     }
  1877 }
  1875 }
  1956 }
  1954 }
  1957 
  1955 
  1958 
  1956 
  1959 void QOpenGLPaintEnginePrivate::drawVertexArrays()
  1957 void QOpenGLPaintEnginePrivate::drawVertexArrays()
  1960 {
  1958 {
       
  1959     if (tess_points_stops.count() == 0)
       
  1960         return;
  1961     glEnableClientState(GL_VERTEX_ARRAY);
  1961     glEnableClientState(GL_VERTEX_ARRAY);
  1962     glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
  1962     glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
  1963     int previous_stop = 0;
  1963     int previous_stop = 0;
  1964     foreach(int stop, tess_points_stops) {
  1964     foreach(int stop, tess_points_stops) {
  1965         glDrawArrays(GL_TRIANGLE_FAN, previous_stop, stop-previous_stop);
  1965         glDrawArrays(GL_TRIANGLE_FAN, previous_stop, stop-previous_stop);
  2268 
  2268 
  2269         glScissor(left, bottom, width, height);
  2269         glScissor(left, bottom, width, height);
  2270         return;
  2270         return;
  2271     }
  2271     }
  2272 
  2272 
  2273 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_1_CL)
  2273 #if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2)
  2274     glClearDepthf(0.0f);
  2274     glClearDepthf(0.0f);
  2275 #else
  2275 #else
  2276     glClearDepth(0.0f);
  2276     glClearDepth(0.0f);
  2277 #endif
  2277 #endif
  2278 
  2278 
  2284     glDepthFunc(GL_ALWAYS);
  2284     glDepthFunc(GL_ALWAYS);
  2285 
  2285 
  2286     const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects();
  2286     const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects();
  2287 
  2287 
  2288     // rectangle count * 2 (triangles) * vertex count * component count (Z omitted)
  2288     // rectangle count * 2 (triangles) * vertex count * component count (Z omitted)
  2289     QDataBuffer<q_vertexType> clipVertex(rects.size()*2*3*2);
  2289     QDataBuffer<GLfloat> clipVertex(rects.size()*2*3*2);
  2290     for (int i = 0; i < rects.size(); ++i) {
  2290     for (int i = 0; i < rects.size(); ++i) {
  2291         q_vertexType x = i2vt(rects.at(i).left());
  2291         GLfloat x = GLfloat(rects.at(i).left());
  2292         q_vertexType w = i2vt(rects.at(i).width());
  2292         GLfloat w = GLfloat(rects.at(i).width());
  2293         q_vertexType h = i2vt(rects.at(i).height());
  2293         GLfloat h = GLfloat(rects.at(i).height());
  2294         q_vertexType y = i2vt(rects.at(i).top());
  2294         GLfloat y = GLfloat(rects.at(i).top());
  2295 
  2295 
  2296         // First triangle
  2296         // First triangle
  2297         clipVertex.add(x);
  2297         clipVertex.add(x);
  2298         clipVertex.add(y);
  2298         clipVertex.add(y);
  2299 
  2299 
  2317     if (rects.size()) {
  2317     if (rects.size()) {
  2318         glMatrixMode(GL_MODELVIEW);
  2318         glMatrixMode(GL_MODELVIEW);
  2319         glLoadIdentity();
  2319         glLoadIdentity();
  2320 
  2320 
  2321         glEnableClientState(GL_VERTEX_ARRAY);
  2321         glEnableClientState(GL_VERTEX_ARRAY);
  2322         glVertexPointer(2, q_vertexTypeEnum, 0, clipVertex.data());
  2322         glVertexPointer(2, GL_FLOAT, 0, clipVertex.data());
  2323 
  2323 
  2324         glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3);
  2324         glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3);
  2325         glDisableClientState(GL_VERTEX_ARRAY);
  2325         glDisableClientState(GL_VERTEX_ARRAY);
  2326         updateGLMatrix();
  2326         updateGLMatrix();
  2327     }
  2327     }
  3109     ,  offscreen(&offs)
  3109     ,  offscreen(&offs)
  3110     ,  maskFragmentProgram(program)
  3110     ,  maskFragmentProgram(program)
  3111 {
  3111 {
  3112 }
  3112 }
  3113 
  3113 
  3114 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
  3114 extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array);
  3115 extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
  3115 extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array);
  3116 
  3116 
  3117 void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
  3117 void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
  3118 {
  3118 {
  3119 #ifdef QT_OPENGL_ES
  3119 #ifdef QT_OPENGL_ES
  3120     Q_UNUSED(rect);
  3120     Q_UNUSED(rect);
  3141 
  3141 
  3142     QVector<QGLTrapezoid> trapezoids = generateTrapezoids();
  3142     QVector<QGLTrapezoid> trapezoids = generateTrapezoids();
  3143 
  3143 
  3144     // clear mask
  3144     // clear mask
  3145     glBlendFunc(GL_ZERO, GL_ZERO); // clear
  3145     glBlendFunc(GL_ZERO, GL_ZERO); // clear
  3146     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3146     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3147     glEnableClientState(GL_VERTEX_ARRAY);
  3147     glEnableClientState(GL_VERTEX_ARRAY);
  3148     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3148     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3149     glDisableClientState(GL_VERTEX_ARRAY);
  3149     glDisableClientState(GL_VERTEX_ARRAY);
  3150 
  3150 
  3151     glBlendFunc(GL_ONE, GL_ONE); // add mask
  3151     glBlendFunc(GL_ONE, GL_ONE); // add mask
  3348 
  3348 
  3349     QTransform translate(1, 0, 0, 1, -ellipseRect.center().x(), -ellipseRect.center().y());
  3349     QTransform translate(1, 0, 0, 1, -ellipseRect.center().x(), -ellipseRect.center().y());
  3350     QTransform gl_to_qt(1, 0, 0, -1, 0, offscreen->drawableSize().height());
  3350     QTransform gl_to_qt(1, 0, 0, -1, 0, offscreen->drawableSize().height());
  3351     QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate;
  3351     QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate;
  3352 
  3352 
  3353     float m[3][4] = { { inv_matrix.m11(), inv_matrix.m12(), inv_matrix.m13() },
  3353     float m[3][4] = { { float(inv_matrix.m11()), float(inv_matrix.m12()), float(inv_matrix.m13()) },
  3354                       { inv_matrix.m21(), inv_matrix.m22(), inv_matrix.m23() },
  3354                       { float(inv_matrix.m21()), float(inv_matrix.m22()), float(inv_matrix.m23()) },
  3355                       { inv_matrix.m31(), inv_matrix.m32(), inv_matrix.m33() } };
  3355                       { float(inv_matrix.m31()), float(inv_matrix.m32()), float(inv_matrix.m33()) } };
  3356 
  3356 
  3357     QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top())
  3357     QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top())
  3358                                                 - (offscreen->offscreenSize().height() - rect.top()));
  3358                                                 - (offscreen->offscreenSize().height() - rect.top()));
  3359 
  3359 
  3360     // last component needs to be 1.0f to avoid Nvidia bug on linux
  3360     // last component needs to be 1.0f to avoid Nvidia bug on linux
  3361     float ellipse_offset[4] = { offs.x(), offs.y(), 0.0f, 1.0f };
  3361     float ellipse_offset[4] = { float(offs.x()), float(offs.y()), 0.0f, 1.0f };
  3362 
  3362 
  3363     GLfloat vertexArray[4 * 2];
  3363     GLfloat vertexArray[4 * 2];
  3364     qt_add_rect_to_array(rect, vertexArray);
  3364     qt_add_rect_to_array(rect, vertexArray);
  3365 
  3365 
  3366     glBlendFunc(GL_ONE, GL_ZERO); // set mask
  3366     glBlendFunc(GL_ONE, GL_ZERO); // set mask
  3372     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M2], m[2]);
  3372     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M2], m[2]);
  3373 
  3373 
  3374     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset);
  3374     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset);
  3375 
  3375 
  3376     glEnableClientState(GL_VERTEX_ARRAY);
  3376     glEnableClientState(GL_VERTEX_ARRAY);
  3377     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3377     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3378     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3378     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3379     glDisableClientState(GL_VERTEX_ARRAY);
  3379     glDisableClientState(GL_VERTEX_ARRAY);
  3380     glDisable(GL_FRAGMENT_PROGRAM_ARB);
  3380     glDisable(GL_FRAGMENT_PROGRAM_ARB);
  3381 #endif
  3381 #endif
  3382 }
  3382 }
  3402 void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r)
  3402 void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r)
  3403 {
  3403 {
  3404     Q_Q(QOpenGLPaintEngine);
  3404     Q_Q(QOpenGLPaintEngine);
  3405     DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect");
  3405     DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect");
  3406 
  3406 
  3407     q_vertexType vertexArray[10];
  3407     GLfloat vertexArray[10];
  3408     qt_add_rect_to_array(r, vertexArray);
  3408     qt_add_rect_to_array(r, vertexArray);
  3409 
  3409 
  3410     if (has_pen)
  3410     if (has_pen)
  3411         QOpenGLCoordinateOffset::enableOffset(this);
  3411         QOpenGLCoordinateOffset::enableOffset(this);
  3412 
  3412 
  3423         bool fast_style = current_style == Qt::LinearGradientPattern
  3423         bool fast_style = current_style == Qt::LinearGradientPattern
  3424                           || current_style == Qt::SolidPattern;
  3424                           || current_style == Qt::SolidPattern;
  3425 
  3425 
  3426         if (fast_style && has_fast_composition_mode) {
  3426         if (fast_style && has_fast_composition_mode) {
  3427             glEnableClientState(GL_VERTEX_ARRAY);
  3427             glEnableClientState(GL_VERTEX_ARRAY);
  3428             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3428             glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3429             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3429             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3430             glDisableClientState(GL_VERTEX_ARRAY);
  3430             glDisableClientState(GL_VERTEX_ARRAY);
  3431         } else {
  3431         } else {
  3432             composite(r);
  3432             composite(r);
  3433         }
  3433         }
  3442             setGradientOps(cpen.brush(), r);
  3442             setGradientOps(cpen.brush(), r);
  3443 
  3443 
  3444             vertexArray[8] = vertexArray[0];
  3444             vertexArray[8] = vertexArray[0];
  3445             vertexArray[9] = vertexArray[1];
  3445             vertexArray[9] = vertexArray[1];
  3446 
  3446 
  3447             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3447             glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3448             glEnableClientState(GL_VERTEX_ARRAY);
  3448             glEnableClientState(GL_VERTEX_ARRAY);
  3449             glDrawArrays(GL_LINE_STRIP, 0, 5);
  3449             glDrawArrays(GL_LINE_STRIP, 0, 5);
  3450             glDisableClientState(GL_VERTEX_ARRAY);
  3450             glDisableClientState(GL_VERTEX_ARRAY);
  3451         } else {
  3451         } else {
  3452             QPainterPath path;
  3452             QPainterPath path;
  3549             }
  3549             }
  3550         }
  3550         }
  3551     }
  3551     }
  3552 }
  3552 }
  3553 
  3553 
  3554 static void addQuadAsTriangle(q_vertexType *quad, q_vertexType *triangle)
  3554 static void addQuadAsTriangle(GLfloat *quad, GLfloat *triangle)
  3555 {
  3555 {
  3556     triangle[0] = quad[0];
  3556     triangle[0] = quad[0];
  3557     triangle[1] = quad[1];
  3557     triangle[1] = quad[1];
  3558 
  3558 
  3559     triangle[2] = quad[2];
  3559     triangle[2] = quad[2];
  3610     }
  3610     }
  3611 
  3611 
  3612     d->flushDrawQueue();
  3612     d->flushDrawQueue();
  3613 
  3613 
  3614     if (d->has_fast_pen) {
  3614     if (d->has_fast_pen) {
  3615         QVarLengthArray<q_vertexType> vertexArray(6 * pointCount);
  3615         QVarLengthArray<GLfloat> vertexArray(6 * pointCount);
  3616 
  3616 
  3617         glMatrixMode(GL_MODELVIEW);
  3617         glMatrixMode(GL_MODELVIEW);
  3618         glPushMatrix();
  3618         glPushMatrix();
  3619         glLoadIdentity();
  3619         glLoadIdentity();
  3620 
  3620 
  3621         int j = 0;
  3621         int j = 0;
  3622         for (int i = 0; i < pointCount; ++i) {
  3622         for (int i = 0; i < pointCount; ++i) {
  3623             QPointF mapped = d->matrix.map(points[i]);
  3623             QPointF mapped = d->matrix.map(points[i]);
  3624 
  3624 
  3625             qreal xf = qRound(mapped.x());
  3625             GLfloat x = GLfloat(qRound(mapped.x()));
  3626             qreal yf = qRound(mapped.y());
  3626             GLfloat y = GLfloat(qRound(mapped.y()));
  3627 
       
  3628             q_vertexType x = f2vt(xf);
       
  3629             q_vertexType y = f2vt(yf);
       
  3630 
  3627 
  3631             vertexArray[j++] = x;
  3628             vertexArray[j++] = x;
  3632             vertexArray[j++] = y - f2vt(0.5);
  3629             vertexArray[j++] = y - 0.5f;
  3633 
  3630 
  3634             vertexArray[j++] = x + f2vt(1.5);
  3631             vertexArray[j++] = x + 1.5f;
  3635             vertexArray[j++] = y + f2vt(1.0);
  3632             vertexArray[j++] = y + 1.0f;
  3636 
  3633 
  3637             vertexArray[j++] = x;
  3634             vertexArray[j++] = x;
  3638             vertexArray[j++] = y + f2vt(1.0);
  3635             vertexArray[j++] = y + 1.0f;
  3639         }
  3636         }
  3640 
  3637 
  3641         glEnableClientState(GL_VERTEX_ARRAY);
  3638         glEnableClientState(GL_VERTEX_ARRAY);
  3642 
  3639 
  3643         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3640         glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3644         glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
  3641         glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
  3645 
  3642 
  3646         glDisableClientState(GL_VERTEX_ARRAY);
  3643         glDisableClientState(GL_VERTEX_ARRAY);
  3647 
  3644 
  3648         glPopMatrix();
  3645         glPopMatrix();
  3655         Q_ASSERT(sizeof(QPointF) == 16);
  3652         Q_ASSERT(sizeof(QPointF) == 16);
  3656         glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3653         glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3657     }
  3654     }
  3658     else {
  3655     else {
  3659         Q_ASSERT(sizeof(QPointF) == 8);
  3656         Q_ASSERT(sizeof(QPointF) == 8);
  3660         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3657         glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3661     }
  3658     }
  3662 
  3659 
  3663     glEnableClientState(GL_VERTEX_ARRAY);
  3660     glEnableClientState(GL_VERTEX_ARRAY);
  3664     glDrawArrays(GL_POINTS, 0, pointCount);
  3661     glDrawArrays(GL_POINTS, 0, pointCount);
  3665     glDisableClientState(GL_VERTEX_ARRAY);
  3662     glDisableClientState(GL_VERTEX_ARRAY);
  3723                         break;
  3720                         break;
  3724                     }
  3721                     }
  3725                 }
  3722                 }
  3726             }
  3723             }
  3727 
  3724 
  3728             q_vertexType endCap = f2vt(d->cpen.capStyle() == Qt::FlatCap ? 0 : 0.5);
  3725             GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f;
  3729             if (useRects) {
  3726             if (useRects) {
  3730                 QVarLengthArray<q_vertexType> vertexArray(12 * lineCount);
  3727                 QVarLengthArray<GLfloat> vertexArray(12 * lineCount);
  3731 
  3728 
  3732                 q_vertexType quad[8];
  3729                 GLfloat quad[8];
  3733                 for (int i = 0; i < lineCount; ++i) {
  3730                 for (int i = 0; i < lineCount; ++i) {
  3734                     q_vertexType x1 = f2vt(lines[i].x1());
  3731                     GLfloat x1 = lines[i].x1();
  3735                     q_vertexType x2 = f2vt(lines[i].x2());
  3732                     GLfloat x2 = lines[i].x2();
  3736                     q_vertexType y1 = f2vt(lines[i].y1());
  3733                     GLfloat y1 = lines[i].y1();
  3737                     q_vertexType y2 = f2vt(lines[i].y2());
  3734                     GLfloat y2 = lines[i].y2();
  3738 
  3735 
  3739                     if (x1 == x2) {
  3736                     if (x1 == x2) {
  3740                         if (y1 > y2)
  3737                         if (y1 > y2)
  3741                             qSwap(y1, y2);
  3738                             qSwap(y1, y2);
  3742 
  3739 
  3743                         quad[0] = x1 - f2vt(0.5);
  3740                         quad[0] = x1 - 0.5f;
  3744                         quad[1] = y1 - endCap;
  3741                         quad[1] = y1 - endCap;
  3745 
  3742 
  3746                         quad[2] = x1 + f2vt(0.5);
  3743                         quad[2] = x1 + 0.5f;
  3747                         quad[3] = y1 - endCap;
  3744                         quad[3] = y1 - endCap;
  3748 
  3745 
  3749                         quad[4] = x1 + f2vt(0.5);
  3746                         quad[4] = x1 + 0.5f;
  3750                         quad[5] = y2 + endCap;
  3747                         quad[5] = y2 + endCap;
  3751 
  3748 
  3752                         quad[6] = x1 - f2vt(0.5);
  3749                         quad[6] = x1 - 0.5f;
  3753                         quad[7] = y2 + endCap;
  3750                         quad[7] = y2 + endCap;
  3754                     } else {
  3751                     } else {
  3755                         if (x1 > x2)
  3752                         if (x1 > x2)
  3756                             qSwap(x1, x2);
  3753                             qSwap(x1, x2);
  3757 
  3754 
  3758                         quad[0] = x1 - endCap;
  3755                         quad[0] = x1 - endCap;
  3759                         quad[1] = y1 + f2vt(0.5);
  3756                         quad[1] = y1 + 0.5f;
  3760 
  3757 
  3761                         quad[2] = x1 - endCap;
  3758                         quad[2] = x1 - endCap;
  3762                         quad[3] = y1 - f2vt(0.5);
  3759                         quad[3] = y1 - 0.5f;
  3763 
  3760 
  3764                         quad[4] = x2 + endCap;
  3761                         quad[4] = x2 + endCap;
  3765                         quad[5] = y1 - f2vt(0.5);
  3762                         quad[5] = y1 - 0.5f;
  3766 
  3763 
  3767                         quad[6] = x2 + endCap;
  3764                         quad[6] = x2 + endCap;
  3768                         quad[7] = y1 + f2vt(0.5);
  3765                         quad[7] = y1 + 0.5f;
  3769                     }
  3766                     }
  3770 
  3767 
  3771                     addQuadAsTriangle(quad, &vertexArray[12*i]);
  3768                     addQuadAsTriangle(quad, &vertexArray[12*i]);
  3772                 }
  3769                 }
  3773 
  3770 
  3774                 glEnableClientState(GL_VERTEX_ARRAY);
  3771                 glEnableClientState(GL_VERTEX_ARRAY);
  3775 
  3772 
  3776                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3773                 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3777                 glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
  3774                 glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
  3778 
  3775 
  3779                 glDisableClientState(GL_VERTEX_ARRAY);
  3776                 glDisableClientState(GL_VERTEX_ARRAY);
  3780             } else {
  3777             } else {
  3781                 QVarLengthArray<q_vertexType> vertexArray(4 * lineCount);
  3778                 QVarLengthArray<GLfloat> vertexArray(4 * lineCount);
  3782                 for (int i = 0; i < lineCount; ++i) {
  3779                 for (int i = 0; i < lineCount; ++i) {
  3783                     const QPointF a = lines[i].p1();
  3780                     const QPointF a = lines[i].p1();
  3784                     vertexArray[4*i]   = f2vt(lines[i].x1());
  3781                     vertexArray[4*i]   = lines[i].x1();
  3785                     vertexArray[4*i+1] = f2vt(lines[i].y1());
  3782                     vertexArray[4*i+1] = lines[i].y1();
  3786                     vertexArray[4*i+2] = f2vt(lines[i].x2());
  3783                     vertexArray[4*i+2] = lines[i].x2();
  3787                     vertexArray[4*i+3] = f2vt(lines[i].y2());
  3784                     vertexArray[4*i+3] = lines[i].y2();
  3788                 }
  3785                 }
  3789 
  3786 
  3790                 glEnableClientState(GL_VERTEX_ARRAY);
  3787                 glEnableClientState(GL_VERTEX_ARRAY);
  3791 
  3788 
  3792                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3789                 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3793                 glDrawArrays(GL_LINES, 0, lineCount*2);
  3790                 glDrawArrays(GL_LINES, 0, lineCount*2);
  3794 
  3791 
  3795                 glVertexPointer(2, q_vertexTypeEnum, 4*sizeof(q_vertexType), vertexArray.constData() + 2);
  3792                 glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2);
  3796                 glDrawArrays(GL_POINTS, 0, lineCount);
  3793                 glDrawArrays(GL_POINTS, 0, lineCount);
  3797 
  3794 
  3798                 glDisableClientState(GL_VERTEX_ARRAY);
  3795                 glDisableClientState(GL_VERTEX_ARRAY);
  3799             }
  3796             }
  3800         } else {
  3797         } else {
  3877                 Q_ASSERT(sizeof(QPointF) == 16);
  3874                 Q_ASSERT(sizeof(QPointF) == 16);
  3878                 glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3875                 glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3879             }
  3876             }
  3880             else {
  3877             else {
  3881                 Q_ASSERT(sizeof(QPointF) == 8);
  3878                 Q_ASSERT(sizeof(QPointF) == 8);
  3882                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3879                 glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3883             }
  3880             }
  3884 
  3881 
  3885             glEnableClientState(GL_VERTEX_ARRAY);
  3882             glEnableClientState(GL_VERTEX_ARRAY);
  3886             glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount);
  3883             glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount);
  3887             glDisableClientState(GL_VERTEX_ARRAY);
  3884             glDisableClientState(GL_VERTEX_ARRAY);
  3896     }
  3893     }
  3897 
  3894 
  3898     if (d->has_pen) {
  3895     if (d->has_pen) {
  3899         if (d->has_fast_pen && !d->high_quality_antialiasing) {
  3896         if (d->has_fast_pen && !d->high_quality_antialiasing) {
  3900             d->setGradientOps(d->cpen.brush(), bounds);
  3897             d->setGradientOps(d->cpen.brush(), bounds);
  3901             QVarLengthArray<q_vertexType> vertexArray(pointCount*2 + 2);
  3898             QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2);
  3902             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3899             glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3903             int i;
  3900             int i;
  3904             for (i=0; i<pointCount; ++i) {
  3901             for (i=0; i<pointCount; ++i) {
  3905                 vertexArray[i*2] = f2vt(points[i].x());
  3902                 vertexArray[i*2] = points[i].x();
  3906                 vertexArray[i*2+1] = f2vt(points[i].y());
  3903                 vertexArray[i*2+1] = points[i].y();
  3907             }
  3904             }
  3908 
  3905 
  3909             glEnableClientState(GL_VERTEX_ARRAY);
  3906             glEnableClientState(GL_VERTEX_ARRAY);
  3910             if (mode != PolylineMode) {
  3907             if (mode != PolylineMode) {
  3911                 vertexArray[i*2] = vertexArray[0];
  3908                 vertexArray[i*2] = vertexArray[0];
  3956     brush_origin = origin;
  3953     brush_origin = origin;
  3957 
  3954 
  3958     enableClipping();
  3955     enableClipping();
  3959 }
  3956 }
  3960 
  3957 
  3961 extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
  3958 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
  3962 
  3959 
  3963 void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
  3960 void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
  3964 {
  3961 {
  3965     QBrush old_brush = cbrush;
  3962     QBrush old_brush = cbrush;
  3966     cbrush = cpen.brush();
  3963     cbrush = cpen.brush();
  4077     for (int i=0; i<path.elementCount(); ++i) {
  4074     for (int i=0; i<path.elementCount(); ++i) {
  4078         const QPainterPath::Element &e = path.elementAt(i);
  4075         const QPainterPath::Element &e = path.elementAt(i);
  4079         switch (e.type) {
  4076         switch (e.type) {
  4080         case QPainterPath::MoveToElement:
  4077         case QPainterPath::MoveToElement:
  4081             if (i != 0) {
  4078             if (i != 0) {
  4082                 glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
  4079                 glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
  4083                 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4080                 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4084                 tess_points.reset();
  4081                 tess_points.reset();
  4085             }
  4082             }
  4086             tess_points.add(QPointF(e.x, e.y));
  4083             tess_points.add(QPointF(e.x, e.y));
  4087 
  4084 
  4127         } // case CurveToElement
  4124         } // case CurveToElement
  4128         default:
  4125         default:
  4129             break;
  4126             break;
  4130         } // end of switch
  4127         } // end of switch
  4131     }
  4128     }
  4132     glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
  4129     glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
  4133     glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4130     glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4134     glDisableClientState(GL_VERTEX_ARRAY);
  4131     glDisableClientState(GL_VERTEX_ARRAY);
  4135 #endif
  4132 #endif
  4136 }
  4133 }
  4137 
  4134 
  4394             glPushMatrix();
  4391             glPushMatrix();
  4395             glRotatef(180.0, 0.0, 1.0, 0.0);
  4392             glRotatef(180.0, 0.0, 1.0, 0.0);
  4396             glRotatef(180.0, 0.0, 0.0, 1.0);
  4393             glRotatef(180.0, 0.0, 0.0, 1.0);
  4397         }
  4394         }
  4398 
  4395 
  4399         q_vertexType vertexArray[4*2];
  4396         GLfloat vertexArray[4*2];
  4400         q_vertexType texCoordArray[4*2];
  4397         GLfloat texCoordArray[4*2];
  4401 
  4398 
  4402         double offset_x = offset.x() / pm.width();
  4399         double offset_x = offset.x() / pm.width();
  4403         double offset_y = offset.y() / pm.height();
  4400         double offset_y = offset.y() / pm.height();
  4404 
  4401 
  4405         qt_add_rect_to_array(r, vertexArray);
  4402         qt_add_rect_to_array(r, vertexArray);
  4406         qt_add_texcoords_to_array(offset_x, offset_y,
  4403         qt_add_texcoords_to_array(offset_x, offset_y,
  4407                                   tc_w + offset_x, tc_h + offset_y, texCoordArray);
  4404                                   tc_w + offset_x, tc_h + offset_y, texCoordArray);
  4408 
  4405 
  4409         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  4406         glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  4410         glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
  4407         glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
  4411 
  4408 
  4412         glEnableClientState(GL_VERTEX_ARRAY);
  4409         glEnableClientState(GL_VERTEX_ARRAY);
  4413         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4410         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4414         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4411         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4415         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4412         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4486         x2 = sr.right();
  4483         x2 = sr.right();
  4487         y1 = sr.bottom();
  4484         y1 = sr.bottom();
  4488         y2 = sr.y();
  4485         y2 = sr.y();
  4489     }
  4486     }
  4490 
  4487 
  4491     q_vertexType vertexArray[4*2];
  4488     GLfloat vertexArray[4*2];
  4492     q_vertexType texCoordArray[4*2];
  4489     GLfloat texCoordArray[4*2];
  4493 
  4490 
  4494     qt_add_rect_to_array(r, vertexArray);
  4491     qt_add_rect_to_array(r, vertexArray);
  4495     qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
  4492     qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
  4496 
  4493 
  4497     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  4494     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  4498     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
  4495     glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
  4499 
  4496 
  4500     glEnableClientState(GL_VERTEX_ARRAY);
  4497     glEnableClientState(GL_VERTEX_ARRAY);
  4501     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4498     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4502     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4499     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4503     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4500     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4558     Q_OBJECT
  4555     Q_OBJECT
  4559 public:
  4556 public:
  4560     QGLGlyphCache() : QObject(0) { current_cache = 0; }
  4557     QGLGlyphCache() : QObject(0) { current_cache = 0; }
  4561     ~QGLGlyphCache();
  4558     ~QGLGlyphCache();
  4562     QGLGlyphCoord *lookup(QFontEngine *, glyph_t);
  4559     QGLGlyphCoord *lookup(QFontEngine *, glyph_t);
  4563     void cacheGlyphs(QGLContext *, const QTextItemInt &, const QVarLengthArray<glyph_t> &);
  4560     void cacheGlyphs(QGLContext *, QFontEngine *, glyph_t *glyphs, int numGlyphs);
  4564     void cleanCache();
  4561     void cleanCache();
  4565     void allocTexture(int width, int height, GLuint texture);
  4562     void allocTexture(int width, int height, GLuint texture);
  4566 
  4563 
  4567 public slots:
  4564 public slots:
  4568     void cleanupContext(const QGLContext *);
  4565     void cleanupContext(const QGLContext *);
  4710     delete old_tex_data;
  4707     delete old_tex_data;
  4711     return im;
  4708     return im;
  4712 }
  4709 }
  4713 #endif
  4710 #endif
  4714 
  4711 
  4715 void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti,
  4712 void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
  4716                                 const QVarLengthArray<glyph_t> &glyphs)
  4713                                 glyph_t *glyphs, int numGlyphs)
  4717 {
  4714 {
  4718     QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context);
  4715     QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context);
  4719     QGLFontGlyphHash *font_cache = 0;
  4716     QGLFontGlyphHash *font_cache = 0;
  4720     const QGLContext *context_key = 0;
  4717     const QGLContext *context_key = 0;
  4721 
  4718 
  4747     } else {
  4744     } else {
  4748         font_cache = dev_it.value();
  4745         font_cache = dev_it.value();
  4749     }
  4746     }
  4750     Q_ASSERT(font_cache != 0);
  4747     Q_ASSERT(font_cache != 0);
  4751 
  4748 
  4752     QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(ti.fontEngine);
  4749     QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine);
  4753     QGLGlyphHash *cache = 0;
  4750     QGLGlyphHash *cache = 0;
  4754     if (cache_it == font_cache->constEnd()) {
  4751     if (cache_it == font_cache->constEnd()) {
  4755         cache = new QGLGlyphHash;
  4752         cache = new QGLGlyphHash;
  4756         font_cache->insert(ti.fontEngine, cache);
  4753         font_cache->insert(fontEngine, cache);
  4757         connect(ti.fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
  4754         connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
  4758     } else {
  4755     } else {
  4759         cache = cache_it.value();
  4756         cache = cache_it.value();
  4760     }
  4757     }
  4761     current_cache = cache;
  4758     current_cache = cache;
  4762 
  4759 
  4763     quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32)
  4760     quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32)
  4764                        | reinterpret_cast<quint64>(ti.fontEngine);
  4761                        | reinterpret_cast<quint64>(fontEngine);
  4765     QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key);
  4762     QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key);
  4766     QGLFontTexture *font_tex;
  4763     QGLFontTexture *font_tex;
  4767     if (it == qt_font_textures.constEnd()) {
  4764     if (it == qt_font_textures.constEnd()) {
  4768         GLuint font_texture;
  4765         GLuint font_texture;
  4769         glGenTextures(1, &font_texture);
  4766         glGenTextures(1, &font_texture);
  4770         GLint tex_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2);
  4767         GLint tex_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2);
  4771         GLint tex_width = qt_next_power_of_two(tex_height*30); // ###
  4768         GLint tex_width = qt_next_power_of_two(tex_height*30); // ###
  4772         GLint max_tex_size;
  4769         GLint max_tex_size;
  4773         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
  4770         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
  4774         Q_ASSERT(max_tex_size > 0);
  4771         Q_ASSERT(max_tex_size > 0);
  4775         if (tex_width > max_tex_size)
  4772         if (tex_width > max_tex_size)
  4787     } else {
  4784     } else {
  4788         font_tex = it.value();
  4785         font_tex = it.value();
  4789         glBindTexture(GL_TEXTURE_2D, font_tex->texture);
  4786         glBindTexture(GL_TEXTURE_2D, font_tex->texture);
  4790     }
  4787     }
  4791 
  4788 
  4792     for (int i=0; i< glyphs.size(); ++i) {
  4789     for (int i=0; i< numGlyphs; ++i) {
  4793         QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
  4790         QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
  4794         if (it == cache->constEnd()) {
  4791         if (it == cache->constEnd()) {
  4795             // render new glyph and put it in the cache
  4792             // render new glyph and put it in the cache
  4796             glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
  4793             glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
  4797             int glyph_width = qRound(metrics.width.toReal())+2;
  4794             int glyph_width = qRound(metrics.width.toReal())+2;
  4798             int glyph_height = qRound(ti.ascent.toReal() + ti.descent.toReal())+2;
  4795             int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2;
  4799 
  4796 
  4800             if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) {
  4797             if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) {
  4801                 int strip_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2);
  4798                 int strip_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2);
  4802                 font_tex->x_offset = x_margin;
  4799                 font_tex->x_offset = x_margin;
  4803                 font_tex->y_offset += strip_height;
  4800                 font_tex->y_offset += strip_height;
  4804                 if (font_tex->y_offset >= font_tex->height) {
  4801                 if (font_tex->y_offset >= font_tex->height) {
  4805                     // get hold of the old font texture
  4802                     // get hold of the old font texture
  4806                     uchar *old_tex_data = (uchar *) malloc(font_tex->width*font_tex->height*2);
  4803                     uchar *old_tex_data = (uchar *) malloc(font_tex->width*font_tex->height*2);
  4829                         ++it;
  4826                         ++it;
  4830                     }
  4827                     }
  4831                 }
  4828                 }
  4832             }
  4829             }
  4833 
  4830 
  4834             QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i]));
  4831             QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i]));
  4835             glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
  4832             glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
  4836             glyph_width = glyph_im.width();
  4833             glyph_width = glyph_im.width();
  4837             Q_ASSERT(glyph_width >= 0);
  4834             Q_ASSERT(glyph_width >= 0);
  4838             // pad the glyph width to an even number
  4835             // pad the glyph width to an even number
  4839             if (glyph_width%2 != 0)
  4836             if (glyph_width%2 != 0)
  4909 void qgl_cleanup_glyph_cache(QGLContext *ctx)
  4906 void qgl_cleanup_glyph_cache(QGLContext *ctx)
  4910 {
  4907 {
  4911     qt_glyph_cache()->cleanupContext(ctx);
  4908     qt_glyph_cache()->cleanupContext(ctx);
  4912 }
  4909 }
  4913 
  4910 
       
  4911 void QOpenGLPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
       
  4912 {
       
  4913     Q_D(QOpenGLPaintEngine);
       
  4914 
       
  4915     d->flushDrawQueue();
       
  4916 
       
  4917     // make sure the glyphs we want to draw are in the cache
       
  4918     qt_glyph_cache()->cacheGlyphs(d->device->context(), textItem->fontEngine, textItem->glyphs,
       
  4919                                   textItem->numGlyphs);
       
  4920 
       
  4921     d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
       
  4922     qt_glColor4ubv(d->pen_color);
       
  4923     glEnable(GL_TEXTURE_2D);
       
  4924 
       
  4925 #ifdef Q_WS_QWS
       
  4926     // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want
       
  4927     // text rendering to update the alpha in the window surface.
       
  4928     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
       
  4929     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
       
  4930 #endif
       
  4931 
       
  4932     // do the actual drawing
       
  4933     GLfloat vertexArray[4*2];
       
  4934     GLfloat texCoordArray[4*2];
       
  4935 
       
  4936     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
       
  4937     glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
       
  4938 
       
  4939     glEnableClientState(GL_VERTEX_ARRAY);
       
  4940     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4941     bool antialias = !(textItem->fontEngine->fontDef.styleStrategy & QFont::NoAntialias)
       
  4942 				   && (d->matrix.type() > QTransform::TxTranslate);
       
  4943     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4944     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4945 
       
  4946     for (int i=0; i< textItem->numGlyphs; ++i) {
       
  4947         QGLGlyphCoord *g = qt_glyph_cache()->lookup(textItem->fontEngine, textItem->glyphs[i]);
       
  4948 
       
  4949         // we don't cache glyphs with no width/height
       
  4950         if (!g)
       
  4951             continue;
       
  4952 
       
  4953         qreal x1, x2, y1, y2;
       
  4954         x1 = g->x;
       
  4955         y1 = g->y;
       
  4956         x2 = x1 + g->width;
       
  4957         y2 = y1 + g->height;
       
  4958 
       
  4959         QPointF logical_pos((textItem->glyphPositions[i].x - g->x_offset).toReal(),
       
  4960                             (textItem->glyphPositions[i].y + g->y_offset).toReal());
       
  4961 
       
  4962         qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray);
       
  4963         qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray);
       
  4964 
       
  4965         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
       
  4966     }
       
  4967 
       
  4968     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4969     glDisableClientState(GL_VERTEX_ARRAY);
       
  4970 
       
  4971     glDisable(GL_TEXTURE_2D);
       
  4972 
       
  4973 #ifdef Q_WS_QWS
       
  4974     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
       
  4975     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
       
  4976 #endif
       
  4977 
       
  4978 }
       
  4979 
  4914 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
  4980 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
  4915 {
  4981 {
  4916     Q_D(QOpenGLPaintEngine);
  4982     Q_D(QOpenGLPaintEngine);
  4917 
  4983 
  4918     const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
  4984     const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
  4923                                   && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
  4989                                   && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
  4924         QPaintEngine::drawTextItem(p, textItem);
  4990         QPaintEngine::drawTextItem(p, textItem);
  4925         return;
  4991         return;
  4926     }
  4992     }
  4927 
  4993 
  4928     d->flushDrawQueue();
       
  4929 
       
  4930     // add the glyphs used to the glyph texture cache
  4994     // add the glyphs used to the glyph texture cache
  4931     QVarLengthArray<QFixedPoint> positions;
  4995     QVarLengthArray<QFixedPoint> positions;
  4932     QVarLengthArray<glyph_t> glyphs;
  4996     QVarLengthArray<glyph_t> glyphs;
  4933     QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y()));
  4997     QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y()));
  4934     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
  4998     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
  4935 
  4999 
  4936     // make sure the glyphs we want to draw are in the cache
  5000     {
  4937     qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs);
  5001         QStaticTextItem staticTextItem;
  4938 
  5002         staticTextItem.chars = ti.chars;
  4939     d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
  5003         staticTextItem.fontEngine = ti.fontEngine;
  4940     qt_glColor4ubv(d->pen_color);
  5004         staticTextItem.glyphs = glyphs.data();
  4941     glEnable(GL_TEXTURE_2D);
  5005         staticTextItem.numChars = ti.num_chars;
  4942 
  5006         staticTextItem.numGlyphs = glyphs.size();
  4943 #ifdef Q_WS_QWS
  5007         staticTextItem.glyphPositions = positions.data();
  4944     // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want
  5008         drawStaticTextItem(&staticTextItem);
  4945     // text rendering to update the alpha in the window surface.
  5009     }
  4946     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
  5010 
  4947     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
       
  4948 #endif
       
  4949 
       
  4950     // do the actual drawing
       
  4951     q_vertexType vertexArray[4*2];
       
  4952     q_vertexType texCoordArray[4*2];
       
  4953 
       
  4954     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
       
  4955     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
       
  4956 
       
  4957     glEnableClientState(GL_VERTEX_ARRAY);
       
  4958     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4959     bool antialias = !(ti.fontEngine->fontDef.styleStrategy & QFont::NoAntialias)
       
  4960                    && (d->matrix.type() > QTransform::TxTranslate);
       
  4961     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4962     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4963 
       
  4964     for (int i=0; i< glyphs.size(); ++i) {
       
  4965         QGLGlyphCoord *g = qt_glyph_cache()->lookup(ti.fontEngine, glyphs[i]);
       
  4966 
       
  4967         // we don't cache glyphs with no width/height
       
  4968         if (!g)
       
  4969             continue;
       
  4970 
       
  4971         qreal x1, x2, y1, y2;
       
  4972         x1 = g->x;
       
  4973         y1 = g->y;
       
  4974         x2 = x1 + g->width;
       
  4975         y2 = y1 + g->height;
       
  4976 
       
  4977         QPointF logical_pos((positions[i].x - g->x_offset).toReal(),
       
  4978                             (positions[i].y + g->y_offset).toReal());
       
  4979 
       
  4980         qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray);
       
  4981         qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray);
       
  4982 
       
  4983         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
       
  4984     }
       
  4985 
       
  4986     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4987     glDisableClientState(GL_VERTEX_ARRAY);
       
  4988 
       
  4989     glDisable(GL_TEXTURE_2D);
       
  4990 
       
  4991 #ifdef Q_WS_QWS
       
  4992     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
       
  4993     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
       
  4994 #endif
       
  4995 }
  5011 }
  4996 
  5012 
  4997 
  5013 
  4998 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect)
  5014 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect)
  4999 {
  5015 {
  5163 {
  5179 {
  5164 #ifdef Q_WS_QWS
  5180 #ifdef Q_WS_QWS
  5165     Q_UNUSED(rect);
  5181     Q_UNUSED(rect);
  5166     Q_UNUSED(maskOffset);
  5182     Q_UNUSED(maskOffset);
  5167 #else
  5183 #else
  5168     q_vertexType vertexArray[8];
  5184     GLfloat vertexArray[8];
  5169     qt_add_rect_to_array(rect, vertexArray);
  5185     qt_add_rect_to_array(rect, vertexArray);
  5170 
  5186 
  5171     composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset);
  5187     composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset);
  5172 #endif
  5188 #endif
  5173 }
  5189 }
  5174 
  5190 
  5175 
  5191 
  5176 void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset)
  5192 void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset)
  5177 {
  5193 {
  5178 #ifdef QT_OPENGL_ES
  5194 #ifdef QT_OPENGL_ES
  5179     Q_UNUSED(primitive);
  5195     Q_UNUSED(primitive);
  5180     Q_UNUSED(vertexArray);
  5196     Q_UNUSED(vertexArray);
  5181     Q_UNUSED(vertexCount);
  5197     Q_UNUSED(vertexCount);
  5194         q->updateCompositionMode(composition_mode);
  5210         q->updateCompositionMode(composition_mode);
  5195     else {
  5211     else {
  5196         qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
  5212         qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
  5197 
  5213 
  5198         for (int i = 0; i < vertexCount; ++i) {
  5214         for (int i = 0; i < vertexCount; ++i) {
  5199             qreal x = vt2f(vertexArray[2 * i]);
  5215             qreal x = vertexArray[2 * i];
  5200             qreal y = vt2f(vertexArray[2 * i + 1]);
  5216             qreal y = vertexArray[2 * i + 1];
  5201 
  5217 
  5202             qreal tx, ty;
  5218             qreal tx, ty;
  5203             matrix.map(x, y, &tx, &ty);
  5219             matrix.map(x, y, &tx, &ty);
  5204 
  5220 
  5205             minX = qMin(minX, tx);
  5221             minX = qMin(minX, tx);
  5254 
  5270 
  5255         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform);
  5271         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform);
  5256     }
  5272     }
  5257 
  5273 
  5258     glEnableClientState(GL_VERTEX_ARRAY);
  5274     glEnableClientState(GL_VERTEX_ARRAY);
  5259     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  5275     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  5260     glEnable(GL_FRAGMENT_PROGRAM_ARB);
  5276     glEnable(GL_FRAGMENT_PROGRAM_ARB);
  5261     GLuint program = qt_gl_program_cache()->getProgram(device->context(),
  5277     GLuint program = qt_gl_program_cache()->getProgram(device->context(),
  5262                                                        fragment_brush,
  5278                                                        fragment_brush,
  5263                                                        fragment_composition_mode, false);
  5279                                                        fragment_composition_mode, false);
  5264     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);
  5280     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);