src/opengl/qpaintengine_opengl.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    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 
  1451     }
  1449     }
  1452 #endif
  1450 #endif
  1453     d->device->endPaint();
  1451     d->device->endPaint();
  1454     qt_mask_texture_cache()->maintainCache();
  1452     qt_mask_texture_cache()->maintainCache();
  1455 
  1453 
       
  1454 #if defined(Q_WS_X11)
       
  1455     // clear out the references we hold for textures bound with the
       
  1456     // texture_from_pixmap extension
       
  1457     ctx->d_func()->boundPixmaps.clear();
       
  1458 #endif
  1456     return true;
  1459     return true;
  1457 }
  1460 }
  1458 
  1461 
  1459 void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
  1462 void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
  1460 {
  1463 {
  1785 class QOpenGLTrapezoidToArrayTessellator : public QOpenGLTessellator
  1788 class QOpenGLTrapezoidToArrayTessellator : public QOpenGLTessellator
  1786 {
  1789 {
  1787 public:
  1790 public:
  1788     QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {}
  1791     QOpenGLTrapezoidToArrayTessellator() : vertices(0), allocated(0), size(0) {}
  1789     ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); }
  1792     ~QOpenGLTrapezoidToArrayTessellator() { free(vertices); }
  1790     q_vertexType *vertices;
  1793     GLfloat *vertices;
  1791     int allocated;
  1794     int allocated;
  1792     int size;
  1795     int size;
  1793     QRectF bounds;
  1796     QRectF bounds;
  1794     void addTrap(const Trapezoid &trap);
  1797     void addTrap(const Trapezoid &trap);
  1795     void tessellate(const QPointF *points, int nPoints, bool winding) {
  1798     void tessellate(const QPointF *points, int nPoints, bool winding) {
  1806     if (size > allocated - 8) {
  1809     if (size > allocated - 8) {
  1807 #else
  1810 #else
  1808     if (size > allocated - 12) {
  1811     if (size > allocated - 12) {
  1809 #endif
  1812 #endif
  1810         allocated = qMax(2*allocated, 512);
  1813         allocated = qMax(2*allocated, 512);
  1811         vertices = (q_vertexType *)realloc(vertices, allocated * sizeof(q_vertexType));
  1814         vertices = (GLfloat *)realloc(vertices, allocated * sizeof(GLfloat));
  1812     }
  1815     }
  1813 
  1816 
  1814     QGLTrapezoid t = toGLTrapezoid(trap);
  1817     QGLTrapezoid t = toGLTrapezoid(trap);
  1815 
  1818 
  1816 #ifndef QT_OPENGL_ES
  1819 #ifndef QT_OPENGL_ES
  1817     vertices[size++] = f2vt(t.topLeftX);
  1820     vertices[size++] = t.topLeftX;
  1818     vertices[size++] = f2vt(t.top);
  1821     vertices[size++] = t.top;
  1819     vertices[size++] = f2vt(t.topRightX);
  1822     vertices[size++] = t.topRightX;
  1820     vertices[size++] = f2vt(t.top);
  1823     vertices[size++] = t.top;
  1821     vertices[size++] = f2vt(t.bottomRightX);
  1824     vertices[size++] = t.bottomRightX;
  1822     vertices[size++] = f2vt(t.bottom);
  1825     vertices[size++] = t.bottom;
  1823     vertices[size++] = f2vt(t.bottomLeftX);
  1826     vertices[size++] = t.bottomLeftX;
  1824     vertices[size++] = f2vt(t.bottom);
  1827     vertices[size++] = t.bottom;
  1825 #else
  1828 #else
  1826     // First triangle
  1829     // First triangle
  1827     vertices[size++] = f2vt(t.topLeftX);
  1830     vertices[size++] = t.topLeftX;
  1828     vertices[size++] = f2vt(t.top);
  1831     vertices[size++] = t.top;
  1829     vertices[size++] = f2vt(t.topRightX);
  1832     vertices[size++] = t.topRightX;
  1830     vertices[size++] = f2vt(t.top);
  1833     vertices[size++] = t.top;
  1831     vertices[size++] = f2vt(t.bottomRightX);
  1834     vertices[size++] = t.bottomRightX;
  1832     vertices[size++] = f2vt(t.bottom);
  1835     vertices[size++] = t.bottom;
  1833 
  1836 
  1834     // Second triangle
  1837     // Second triangle
  1835     vertices[size++] = f2vt(t.bottomLeftX);
  1838     vertices[size++] = t.bottomLeftX;
  1836     vertices[size++] = f2vt(t.bottom);
  1839     vertices[size++] = t.bottom;
  1837     vertices[size++] = f2vt(t.topLeftX);
  1840     vertices[size++] = t.topLeftX;
  1838     vertices[size++] = f2vt(t.top);
  1841     vertices[size++] = t.top;
  1839     vertices[size++] = f2vt(t.bottomRightX);
  1842     vertices[size++] = t.bottomRightX;
  1840     vertices[size++] = f2vt(t.bottom);
  1843     vertices[size++] = t.bottom;
  1841 #endif
  1844 #endif
  1842 }
  1845 }
  1843 
  1846 
  1844 
  1847 
  1845 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
  1848 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
  1862 #endif
  1865 #endif
  1863 
  1866 
  1864     if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) {
  1867     if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) {
  1865         composite(geometry_mode, tessellator.vertices, tessellator.size / 2);
  1868         composite(geometry_mode, tessellator.vertices, tessellator.size / 2);
  1866     } else {
  1869     } else {
  1867         glVertexPointer(2, q_vertexTypeEnum, 0, tessellator.vertices);
  1870         glVertexPointer(2, GL_FLOAT, 0, tessellator.vertices);
  1868         glEnableClientState(GL_VERTEX_ARRAY);
  1871         glEnableClientState(GL_VERTEX_ARRAY);
  1869         glDrawArrays(geometry_mode, 0, tessellator.size/2);
  1872         glDrawArrays(geometry_mode, 0, tessellator.size/2);
  1870         glDisableClientState(GL_VERTEX_ARRAY);
  1873         glDisableClientState(GL_VERTEX_ARRAY);
  1871     }
  1874     }
  1872 }
  1875 }
  1951 }
  1954 }
  1952 
  1955 
  1953 
  1956 
  1954 void QOpenGLPaintEnginePrivate::drawVertexArrays()
  1957 void QOpenGLPaintEnginePrivate::drawVertexArrays()
  1955 {
  1958 {
       
  1959     if (tess_points_stops.count() == 0)
       
  1960         return;
  1956     glEnableClientState(GL_VERTEX_ARRAY);
  1961     glEnableClientState(GL_VERTEX_ARRAY);
  1957     glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
  1962     glVertexPointer(2, GL_DOUBLE, 0, tess_points.data());
  1958     int previous_stop = 0;
  1963     int previous_stop = 0;
  1959     foreach(int stop, tess_points_stops) {
  1964     foreach(int stop, tess_points_stops) {
  1960         glDrawArrays(GL_TRIANGLE_FAN, previous_stop, stop-previous_stop);
  1965         glDrawArrays(GL_TRIANGLE_FAN, previous_stop, stop-previous_stop);
  2263 
  2268 
  2264         glScissor(left, bottom, width, height);
  2269         glScissor(left, bottom, width, height);
  2265         return;
  2270         return;
  2266     }
  2271     }
  2267 
  2272 
  2268 #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)
  2269     glClearDepthf(0.0f);
  2274     glClearDepthf(0.0f);
  2270 #else
  2275 #else
  2271     glClearDepth(0.0f);
  2276     glClearDepth(0.0f);
  2272 #endif
  2277 #endif
  2273 
  2278 
  2279     glDepthFunc(GL_ALWAYS);
  2284     glDepthFunc(GL_ALWAYS);
  2280 
  2285 
  2281     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();
  2282 
  2287 
  2283     // rectangle count * 2 (triangles) * vertex count * component count (Z omitted)
  2288     // rectangle count * 2 (triangles) * vertex count * component count (Z omitted)
  2284     QDataBuffer<q_vertexType> clipVertex(rects.size()*2*3*2);
  2289     QDataBuffer<GLfloat> clipVertex(rects.size()*2*3*2);
  2285     for (int i = 0; i < rects.size(); ++i) {
  2290     for (int i = 0; i < rects.size(); ++i) {
  2286         q_vertexType x = i2vt(rects.at(i).left());
  2291         GLfloat x = GLfloat(rects.at(i).left());
  2287         q_vertexType w = i2vt(rects.at(i).width());
  2292         GLfloat w = GLfloat(rects.at(i).width());
  2288         q_vertexType h = i2vt(rects.at(i).height());
  2293         GLfloat h = GLfloat(rects.at(i).height());
  2289         q_vertexType y = i2vt(rects.at(i).top());
  2294         GLfloat y = GLfloat(rects.at(i).top());
  2290 
  2295 
  2291         // First triangle
  2296         // First triangle
  2292         clipVertex.add(x);
  2297         clipVertex.add(x);
  2293         clipVertex.add(y);
  2298         clipVertex.add(y);
  2294 
  2299 
  2312     if (rects.size()) {
  2317     if (rects.size()) {
  2313         glMatrixMode(GL_MODELVIEW);
  2318         glMatrixMode(GL_MODELVIEW);
  2314         glLoadIdentity();
  2319         glLoadIdentity();
  2315 
  2320 
  2316         glEnableClientState(GL_VERTEX_ARRAY);
  2321         glEnableClientState(GL_VERTEX_ARRAY);
  2317         glVertexPointer(2, q_vertexTypeEnum, 0, clipVertex.data());
  2322         glVertexPointer(2, GL_FLOAT, 0, clipVertex.data());
  2318 
  2323 
  2319         glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3);
  2324         glDrawArrays(GL_TRIANGLES, 0, rects.size()*2*3);
  2320         glDisableClientState(GL_VERTEX_ARRAY);
  2325         glDisableClientState(GL_VERTEX_ARRAY);
  2321         updateGLMatrix();
  2326         updateGLMatrix();
  2322     }
  2327     }
  3104     ,  offscreen(&offs)
  3109     ,  offscreen(&offs)
  3105     ,  maskFragmentProgram(program)
  3110     ,  maskFragmentProgram(program)
  3106 {
  3111 {
  3107 }
  3112 }
  3108 
  3113 
  3109 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);
  3110 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);
  3111 
  3116 
  3112 void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
  3117 void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
  3113 {
  3118 {
  3114 #ifdef QT_OPENGL_ES
  3119 #ifdef QT_OPENGL_ES
  3115     Q_UNUSED(rect);
  3120     Q_UNUSED(rect);
  3136 
  3141 
  3137     QVector<QGLTrapezoid> trapezoids = generateTrapezoids();
  3142     QVector<QGLTrapezoid> trapezoids = generateTrapezoids();
  3138 
  3143 
  3139     // clear mask
  3144     // clear mask
  3140     glBlendFunc(GL_ZERO, GL_ZERO); // clear
  3145     glBlendFunc(GL_ZERO, GL_ZERO); // clear
  3141     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3146     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3142     glEnableClientState(GL_VERTEX_ARRAY);
  3147     glEnableClientState(GL_VERTEX_ARRAY);
  3143     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3148     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3144     glDisableClientState(GL_VERTEX_ARRAY);
  3149     glDisableClientState(GL_VERTEX_ARRAY);
  3145 
  3150 
  3146     glBlendFunc(GL_ONE, GL_ONE); // add mask
  3151     glBlendFunc(GL_ONE, GL_ONE); // add mask
  3343 
  3348 
  3344     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());
  3345     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());
  3346     QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate;
  3351     QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate;
  3347 
  3352 
  3348     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()) },
  3349                       { inv_matrix.m21(), inv_matrix.m22(), inv_matrix.m23() },
  3354                       { float(inv_matrix.m21()), float(inv_matrix.m22()), float(inv_matrix.m23()) },
  3350                       { inv_matrix.m31(), inv_matrix.m32(), inv_matrix.m33() } };
  3355                       { float(inv_matrix.m31()), float(inv_matrix.m32()), float(inv_matrix.m33()) } };
  3351 
  3356 
  3352     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())
  3353                                                 - (offscreen->offscreenSize().height() - rect.top()));
  3358                                                 - (offscreen->offscreenSize().height() - rect.top()));
  3354 
  3359 
  3355     // 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
  3356     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 };
  3357 
  3362 
  3358     GLfloat vertexArray[4 * 2];
  3363     GLfloat vertexArray[4 * 2];
  3359     qt_add_rect_to_array(rect, vertexArray);
  3364     qt_add_rect_to_array(rect, vertexArray);
  3360 
  3365 
  3361     glBlendFunc(GL_ONE, GL_ZERO); // set mask
  3366     glBlendFunc(GL_ONE, GL_ZERO); // set mask
  3367     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]);
  3368 
  3373 
  3369     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset);
  3374     glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset);
  3370 
  3375 
  3371     glEnableClientState(GL_VERTEX_ARRAY);
  3376     glEnableClientState(GL_VERTEX_ARRAY);
  3372     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3377     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3373     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3378     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3374     glDisableClientState(GL_VERTEX_ARRAY);
  3379     glDisableClientState(GL_VERTEX_ARRAY);
  3375     glDisable(GL_FRAGMENT_PROGRAM_ARB);
  3380     glDisable(GL_FRAGMENT_PROGRAM_ARB);
  3376 #endif
  3381 #endif
  3377 }
  3382 }
  3397 void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r)
  3402 void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r)
  3398 {
  3403 {
  3399     Q_Q(QOpenGLPaintEngine);
  3404     Q_Q(QOpenGLPaintEngine);
  3400     DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect");
  3405     DEBUG_ONCE_STR("QOpenGLPaintEngine::drawRects(): drawing fast rect");
  3401 
  3406 
  3402     q_vertexType vertexArray[10];
  3407     GLfloat vertexArray[10];
  3403     qt_add_rect_to_array(r, vertexArray);
  3408     qt_add_rect_to_array(r, vertexArray);
  3404 
  3409 
  3405     if (has_pen)
  3410     if (has_pen)
  3406         QOpenGLCoordinateOffset::enableOffset(this);
  3411         QOpenGLCoordinateOffset::enableOffset(this);
  3407 
  3412 
  3418         bool fast_style = current_style == Qt::LinearGradientPattern
  3423         bool fast_style = current_style == Qt::LinearGradientPattern
  3419                           || current_style == Qt::SolidPattern;
  3424                           || current_style == Qt::SolidPattern;
  3420 
  3425 
  3421         if (fast_style && has_fast_composition_mode) {
  3426         if (fast_style && has_fast_composition_mode) {
  3422             glEnableClientState(GL_VERTEX_ARRAY);
  3427             glEnableClientState(GL_VERTEX_ARRAY);
  3423             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3428             glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3424             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3429             glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  3425             glDisableClientState(GL_VERTEX_ARRAY);
  3430             glDisableClientState(GL_VERTEX_ARRAY);
  3426         } else {
  3431         } else {
  3427             composite(r);
  3432             composite(r);
  3428         }
  3433         }
  3437             setGradientOps(cpen.brush(), r);
  3442             setGradientOps(cpen.brush(), r);
  3438 
  3443 
  3439             vertexArray[8] = vertexArray[0];
  3444             vertexArray[8] = vertexArray[0];
  3440             vertexArray[9] = vertexArray[1];
  3445             vertexArray[9] = vertexArray[1];
  3441 
  3446 
  3442             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3447             glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3443             glEnableClientState(GL_VERTEX_ARRAY);
  3448             glEnableClientState(GL_VERTEX_ARRAY);
  3444             glDrawArrays(GL_LINE_STRIP, 0, 5);
  3449             glDrawArrays(GL_LINE_STRIP, 0, 5);
  3445             glDisableClientState(GL_VERTEX_ARRAY);
  3450             glDisableClientState(GL_VERTEX_ARRAY);
  3446         } else {
  3451         } else {
  3447             QPainterPath path;
  3452             QPainterPath path;
  3544             }
  3549             }
  3545         }
  3550         }
  3546     }
  3551     }
  3547 }
  3552 }
  3548 
  3553 
  3549 static void addQuadAsTriangle(q_vertexType *quad, q_vertexType *triangle)
  3554 static void addQuadAsTriangle(GLfloat *quad, GLfloat *triangle)
  3550 {
  3555 {
  3551     triangle[0] = quad[0];
  3556     triangle[0] = quad[0];
  3552     triangle[1] = quad[1];
  3557     triangle[1] = quad[1];
  3553 
  3558 
  3554     triangle[2] = quad[2];
  3559     triangle[2] = quad[2];
  3605     }
  3610     }
  3606 
  3611 
  3607     d->flushDrawQueue();
  3612     d->flushDrawQueue();
  3608 
  3613 
  3609     if (d->has_fast_pen) {
  3614     if (d->has_fast_pen) {
  3610         QVarLengthArray<q_vertexType> vertexArray(6 * pointCount);
  3615         QVarLengthArray<GLfloat> vertexArray(6 * pointCount);
  3611 
  3616 
  3612         glMatrixMode(GL_MODELVIEW);
  3617         glMatrixMode(GL_MODELVIEW);
  3613         glPushMatrix();
  3618         glPushMatrix();
  3614         glLoadIdentity();
  3619         glLoadIdentity();
  3615 
  3620 
  3616         int j = 0;
  3621         int j = 0;
  3617         for (int i = 0; i < pointCount; ++i) {
  3622         for (int i = 0; i < pointCount; ++i) {
  3618             QPointF mapped = d->matrix.map(points[i]);
  3623             QPointF mapped = d->matrix.map(points[i]);
  3619 
  3624 
  3620             qreal xf = qRound(mapped.x());
  3625             GLfloat x = GLfloat(qRound(mapped.x()));
  3621             qreal yf = qRound(mapped.y());
  3626             GLfloat y = GLfloat(qRound(mapped.y()));
  3622 
       
  3623             q_vertexType x = f2vt(xf);
       
  3624             q_vertexType y = f2vt(yf);
       
  3625 
  3627 
  3626             vertexArray[j++] = x;
  3628             vertexArray[j++] = x;
  3627             vertexArray[j++] = y - f2vt(0.5);
  3629             vertexArray[j++] = y - 0.5f;
  3628 
  3630 
  3629             vertexArray[j++] = x + f2vt(1.5);
  3631             vertexArray[j++] = x + 1.5f;
  3630             vertexArray[j++] = y + f2vt(1.0);
  3632             vertexArray[j++] = y + 1.0f;
  3631 
  3633 
  3632             vertexArray[j++] = x;
  3634             vertexArray[j++] = x;
  3633             vertexArray[j++] = y + f2vt(1.0);
  3635             vertexArray[j++] = y + 1.0f;
  3634         }
  3636         }
  3635 
  3637 
  3636         glEnableClientState(GL_VERTEX_ARRAY);
  3638         glEnableClientState(GL_VERTEX_ARRAY);
  3637 
  3639 
  3638         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3640         glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3639         glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
  3641         glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
  3640 
  3642 
  3641         glDisableClientState(GL_VERTEX_ARRAY);
  3643         glDisableClientState(GL_VERTEX_ARRAY);
  3642 
  3644 
  3643         glPopMatrix();
  3645         glPopMatrix();
  3650         Q_ASSERT(sizeof(QPointF) == 16);
  3652         Q_ASSERT(sizeof(QPointF) == 16);
  3651         glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3653         glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3652     }
  3654     }
  3653     else {
  3655     else {
  3654         Q_ASSERT(sizeof(QPointF) == 8);
  3656         Q_ASSERT(sizeof(QPointF) == 8);
  3655         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3657         glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3656     }
  3658     }
  3657 
  3659 
  3658     glEnableClientState(GL_VERTEX_ARRAY);
  3660     glEnableClientState(GL_VERTEX_ARRAY);
  3659     glDrawArrays(GL_POINTS, 0, pointCount);
  3661     glDrawArrays(GL_POINTS, 0, pointCount);
  3660     glDisableClientState(GL_VERTEX_ARRAY);
  3662     glDisableClientState(GL_VERTEX_ARRAY);
  3718                         break;
  3720                         break;
  3719                     }
  3721                     }
  3720                 }
  3722                 }
  3721             }
  3723             }
  3722 
  3724 
  3723             q_vertexType endCap = f2vt(d->cpen.capStyle() == Qt::FlatCap ? 0 : 0.5);
  3725             GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f;
  3724             if (useRects) {
  3726             if (useRects) {
  3725                 QVarLengthArray<q_vertexType> vertexArray(12 * lineCount);
  3727                 QVarLengthArray<GLfloat> vertexArray(12 * lineCount);
  3726 
  3728 
  3727                 q_vertexType quad[8];
  3729                 GLfloat quad[8];
  3728                 for (int i = 0; i < lineCount; ++i) {
  3730                 for (int i = 0; i < lineCount; ++i) {
  3729                     q_vertexType x1 = f2vt(lines[i].x1());
  3731                     GLfloat x1 = lines[i].x1();
  3730                     q_vertexType x2 = f2vt(lines[i].x2());
  3732                     GLfloat x2 = lines[i].x2();
  3731                     q_vertexType y1 = f2vt(lines[i].y1());
  3733                     GLfloat y1 = lines[i].y1();
  3732                     q_vertexType y2 = f2vt(lines[i].y2());
  3734                     GLfloat y2 = lines[i].y2();
  3733 
  3735 
  3734                     if (x1 == x2) {
  3736                     if (x1 == x2) {
  3735                         if (y1 > y2)
  3737                         if (y1 > y2)
  3736                             qSwap(y1, y2);
  3738                             qSwap(y1, y2);
  3737 
  3739 
  3738                         quad[0] = x1 - f2vt(0.5);
  3740                         quad[0] = x1 - 0.5f;
  3739                         quad[1] = y1 - endCap;
  3741                         quad[1] = y1 - endCap;
  3740 
  3742 
  3741                         quad[2] = x1 + f2vt(0.5);
  3743                         quad[2] = x1 + 0.5f;
  3742                         quad[3] = y1 - endCap;
  3744                         quad[3] = y1 - endCap;
  3743 
  3745 
  3744                         quad[4] = x1 + f2vt(0.5);
  3746                         quad[4] = x1 + 0.5f;
  3745                         quad[5] = y2 + endCap;
  3747                         quad[5] = y2 + endCap;
  3746 
  3748 
  3747                         quad[6] = x1 - f2vt(0.5);
  3749                         quad[6] = x1 - 0.5f;
  3748                         quad[7] = y2 + endCap;
  3750                         quad[7] = y2 + endCap;
  3749                     } else {
  3751                     } else {
  3750                         if (x1 > x2)
  3752                         if (x1 > x2)
  3751                             qSwap(x1, x2);
  3753                             qSwap(x1, x2);
  3752 
  3754 
  3753                         quad[0] = x1 - endCap;
  3755                         quad[0] = x1 - endCap;
  3754                         quad[1] = y1 + f2vt(0.5);
  3756                         quad[1] = y1 + 0.5f;
  3755 
  3757 
  3756                         quad[2] = x1 - endCap;
  3758                         quad[2] = x1 - endCap;
  3757                         quad[3] = y1 - f2vt(0.5);
  3759                         quad[3] = y1 - 0.5f;
  3758 
  3760 
  3759                         quad[4] = x2 + endCap;
  3761                         quad[4] = x2 + endCap;
  3760                         quad[5] = y1 - f2vt(0.5);
  3762                         quad[5] = y1 - 0.5f;
  3761 
  3763 
  3762                         quad[6] = x2 + endCap;
  3764                         quad[6] = x2 + endCap;
  3763                         quad[7] = y1 + f2vt(0.5);
  3765                         quad[7] = y1 + 0.5f;
  3764                     }
  3766                     }
  3765 
  3767 
  3766                     addQuadAsTriangle(quad, &vertexArray[12*i]);
  3768                     addQuadAsTriangle(quad, &vertexArray[12*i]);
  3767                 }
  3769                 }
  3768 
  3770 
  3769                 glEnableClientState(GL_VERTEX_ARRAY);
  3771                 glEnableClientState(GL_VERTEX_ARRAY);
  3770 
  3772 
  3771                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3773                 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3772                 glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
  3774                 glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
  3773 
  3775 
  3774                 glDisableClientState(GL_VERTEX_ARRAY);
  3776                 glDisableClientState(GL_VERTEX_ARRAY);
  3775             } else {
  3777             } else {
  3776                 QVarLengthArray<q_vertexType> vertexArray(4 * lineCount);
  3778                 QVarLengthArray<GLfloat> vertexArray(4 * lineCount);
  3777                 for (int i = 0; i < lineCount; ++i) {
  3779                 for (int i = 0; i < lineCount; ++i) {
  3778                     const QPointF a = lines[i].p1();
  3780                     const QPointF a = lines[i].p1();
  3779                     vertexArray[4*i]   = f2vt(lines[i].x1());
  3781                     vertexArray[4*i]   = lines[i].x1();
  3780                     vertexArray[4*i+1] = f2vt(lines[i].y1());
  3782                     vertexArray[4*i+1] = lines[i].y1();
  3781                     vertexArray[4*i+2] = f2vt(lines[i].x2());
  3783                     vertexArray[4*i+2] = lines[i].x2();
  3782                     vertexArray[4*i+3] = f2vt(lines[i].y2());
  3784                     vertexArray[4*i+3] = lines[i].y2();
  3783                 }
  3785                 }
  3784 
  3786 
  3785                 glEnableClientState(GL_VERTEX_ARRAY);
  3787                 glEnableClientState(GL_VERTEX_ARRAY);
  3786 
  3788 
  3787                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3789                 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3788                 glDrawArrays(GL_LINES, 0, lineCount*2);
  3790                 glDrawArrays(GL_LINES, 0, lineCount*2);
  3789 
  3791 
  3790                 glVertexPointer(2, q_vertexTypeEnum, 4*sizeof(q_vertexType), vertexArray.constData() + 2);
  3792                 glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2);
  3791                 glDrawArrays(GL_POINTS, 0, lineCount);
  3793                 glDrawArrays(GL_POINTS, 0, lineCount);
  3792 
  3794 
  3793                 glDisableClientState(GL_VERTEX_ARRAY);
  3795                 glDisableClientState(GL_VERTEX_ARRAY);
  3794             }
  3796             }
  3795         } else {
  3797         } else {
  3872                 Q_ASSERT(sizeof(QPointF) == 16);
  3874                 Q_ASSERT(sizeof(QPointF) == 16);
  3873                 glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3875                 glVertexPointer(2, GL_DOUBLE, 0, vertexArray);
  3874             }
  3876             }
  3875             else {
  3877             else {
  3876                 Q_ASSERT(sizeof(QPointF) == 8);
  3878                 Q_ASSERT(sizeof(QPointF) == 8);
  3877                 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  3879                 glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  3878             }
  3880             }
  3879 
  3881 
  3880             glEnableClientState(GL_VERTEX_ARRAY);
  3882             glEnableClientState(GL_VERTEX_ARRAY);
  3881             glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount);
  3883             glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount);
  3882             glDisableClientState(GL_VERTEX_ARRAY);
  3884             glDisableClientState(GL_VERTEX_ARRAY);
  3891     }
  3893     }
  3892 
  3894 
  3893     if (d->has_pen) {
  3895     if (d->has_pen) {
  3894         if (d->has_fast_pen && !d->high_quality_antialiasing) {
  3896         if (d->has_fast_pen && !d->high_quality_antialiasing) {
  3895             d->setGradientOps(d->cpen.brush(), bounds);
  3897             d->setGradientOps(d->cpen.brush(), bounds);
  3896             QVarLengthArray<q_vertexType> vertexArray(pointCount*2 + 2);
  3898             QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2);
  3897             glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData());
  3899             glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
  3898             int i;
  3900             int i;
  3899             for (i=0; i<pointCount; ++i) {
  3901             for (i=0; i<pointCount; ++i) {
  3900                 vertexArray[i*2] = f2vt(points[i].x());
  3902                 vertexArray[i*2] = points[i].x();
  3901                 vertexArray[i*2+1] = f2vt(points[i].y());
  3903                 vertexArray[i*2+1] = points[i].y();
  3902             }
  3904             }
  3903 
  3905 
  3904             glEnableClientState(GL_VERTEX_ARRAY);
  3906             glEnableClientState(GL_VERTEX_ARRAY);
  3905             if (mode != PolylineMode) {
  3907             if (mode != PolylineMode) {
  3906                 vertexArray[i*2] = vertexArray[0];
  3908                 vertexArray[i*2] = vertexArray[0];
  3951     brush_origin = origin;
  3953     brush_origin = origin;
  3952 
  3954 
  3953     enableClipping();
  3955     enableClipping();
  3954 }
  3956 }
  3955 
  3957 
  3956 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
  3957 
  3959 
  3958 void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
  3960 void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_cache)
  3959 {
  3961 {
  3960     QBrush old_brush = cbrush;
  3962     QBrush old_brush = cbrush;
  3961     cbrush = cpen.brush();
  3963     cbrush = cpen.brush();
  4072     for (int i=0; i<path.elementCount(); ++i) {
  4074     for (int i=0; i<path.elementCount(); ++i) {
  4073         const QPainterPath::Element &e = path.elementAt(i);
  4075         const QPainterPath::Element &e = path.elementAt(i);
  4074         switch (e.type) {
  4076         switch (e.type) {
  4075         case QPainterPath::MoveToElement:
  4077         case QPainterPath::MoveToElement:
  4076             if (i != 0) {
  4078             if (i != 0) {
  4077                 glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
  4079                 glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
  4078                 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4080                 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4079                 tess_points.reset();
  4081                 tess_points.reset();
  4080             }
  4082             }
  4081             tess_points.add(QPointF(e.x, e.y));
  4083             tess_points.add(QPointF(e.x, e.y));
  4082 
  4084 
  4122         } // case CurveToElement
  4124         } // case CurveToElement
  4123         default:
  4125         default:
  4124             break;
  4126             break;
  4125         } // end of switch
  4127         } // end of switch
  4126     }
  4128     }
  4127     glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data());
  4129     glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
  4128     glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4130     glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
  4129     glDisableClientState(GL_VERTEX_ARRAY);
  4131     glDisableClientState(GL_VERTEX_ARRAY);
  4130 #endif
  4132 #endif
  4131 }
  4133 }
  4132 
  4134 
  4389             glPushMatrix();
  4391             glPushMatrix();
  4390             glRotatef(180.0, 0.0, 1.0, 0.0);
  4392             glRotatef(180.0, 0.0, 1.0, 0.0);
  4391             glRotatef(180.0, 0.0, 0.0, 1.0);
  4393             glRotatef(180.0, 0.0, 0.0, 1.0);
  4392         }
  4394         }
  4393 
  4395 
  4394         q_vertexType vertexArray[4*2];
  4396         GLfloat vertexArray[4*2];
  4395         q_vertexType texCoordArray[4*2];
  4397         GLfloat texCoordArray[4*2];
  4396 
  4398 
  4397         double offset_x = offset.x() / pm.width();
  4399         double offset_x = offset.x() / pm.width();
  4398         double offset_y = offset.y() / pm.height();
  4400         double offset_y = offset.y() / pm.height();
  4399 
  4401 
  4400         qt_add_rect_to_array(r, vertexArray);
  4402         qt_add_rect_to_array(r, vertexArray);
  4401         qt_add_texcoords_to_array(offset_x, offset_y,
  4403         qt_add_texcoords_to_array(offset_x, offset_y,
  4402                                   tc_w + offset_x, tc_h + offset_y, texCoordArray);
  4404                                   tc_w + offset_x, tc_h + offset_y, texCoordArray);
  4403 
  4405 
  4404         glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  4406         glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  4405         glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
  4407         glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
  4406 
  4408 
  4407         glEnableClientState(GL_VERTEX_ARRAY);
  4409         glEnableClientState(GL_VERTEX_ARRAY);
  4408         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4410         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4409         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4411         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4410         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4412         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4481         x2 = sr.right();
  4483         x2 = sr.right();
  4482         y1 = sr.bottom();
  4484         y1 = sr.bottom();
  4483         y2 = sr.y();
  4485         y2 = sr.y();
  4484     }
  4486     }
  4485 
  4487 
  4486     q_vertexType vertexArray[4*2];
  4488     GLfloat vertexArray[4*2];
  4487     q_vertexType texCoordArray[4*2];
  4489     GLfloat texCoordArray[4*2];
  4488 
  4490 
  4489     qt_add_rect_to_array(r, vertexArray);
  4491     qt_add_rect_to_array(r, vertexArray);
  4490     qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
  4492     qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray);
  4491 
  4493 
  4492     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  4494     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  4493     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
  4495     glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
  4494 
  4496 
  4495     glEnableClientState(GL_VERTEX_ARRAY);
  4497     glEnableClientState(GL_VERTEX_ARRAY);
  4496     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4498     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  4497     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4499     glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
  4498     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4500     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  4553     Q_OBJECT
  4555     Q_OBJECT
  4554 public:
  4556 public:
  4555     QGLGlyphCache() : QObject(0) { current_cache = 0; }
  4557     QGLGlyphCache() : QObject(0) { current_cache = 0; }
  4556     ~QGLGlyphCache();
  4558     ~QGLGlyphCache();
  4557     QGLGlyphCoord *lookup(QFontEngine *, glyph_t);
  4559     QGLGlyphCoord *lookup(QFontEngine *, glyph_t);
  4558     void cacheGlyphs(QGLContext *, const QTextItemInt &, const QVarLengthArray<glyph_t> &);
  4560     void cacheGlyphs(QGLContext *, QFontEngine *, glyph_t *glyphs, int numGlyphs);
  4559     void cleanCache();
  4561     void cleanCache();
  4560     void allocTexture(int width, int height, GLuint texture);
  4562     void allocTexture(int width, int height, GLuint texture);
  4561 
  4563 
  4562 public slots:
  4564 public slots:
  4563     void cleanupContext(const QGLContext *);
  4565     void cleanupContext(const QGLContext *);
  4705     delete old_tex_data;
  4707     delete old_tex_data;
  4706     return im;
  4708     return im;
  4707 }
  4709 }
  4708 #endif
  4710 #endif
  4709 
  4711 
  4710 void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti,
  4712 void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine,
  4711                                 const QVarLengthArray<glyph_t> &glyphs)
  4713                                 glyph_t *glyphs, int numGlyphs)
  4712 {
  4714 {
  4713     QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context);
  4715     QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context);
  4714     QGLFontGlyphHash *font_cache = 0;
  4716     QGLFontGlyphHash *font_cache = 0;
  4715     const QGLContext *context_key = 0;
  4717     const QGLContext *context_key = 0;
  4716 
  4718 
  4742     } else {
  4744     } else {
  4743         font_cache = dev_it.value();
  4745         font_cache = dev_it.value();
  4744     }
  4746     }
  4745     Q_ASSERT(font_cache != 0);
  4747     Q_ASSERT(font_cache != 0);
  4746 
  4748 
  4747     QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(ti.fontEngine);
  4749     QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine);
  4748     QGLGlyphHash *cache = 0;
  4750     QGLGlyphHash *cache = 0;
  4749     if (cache_it == font_cache->constEnd()) {
  4751     if (cache_it == font_cache->constEnd()) {
  4750         cache = new QGLGlyphHash;
  4752         cache = new QGLGlyphHash;
  4751         font_cache->insert(ti.fontEngine, cache);
  4753         font_cache->insert(fontEngine, cache);
  4752         connect(ti.fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
  4754         connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*)));
  4753     } else {
  4755     } else {
  4754         cache = cache_it.value();
  4756         cache = cache_it.value();
  4755     }
  4757     }
  4756     current_cache = cache;
  4758     current_cache = cache;
  4757 
  4759 
  4758     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)
  4759                        | reinterpret_cast<quint64>(ti.fontEngine);
  4761                        | reinterpret_cast<quint64>(fontEngine);
  4760     QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key);
  4762     QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key);
  4761     QGLFontTexture *font_tex;
  4763     QGLFontTexture *font_tex;
  4762     if (it == qt_font_textures.constEnd()) {
  4764     if (it == qt_font_textures.constEnd()) {
  4763         GLuint font_texture;
  4765         GLuint font_texture;
  4764         glGenTextures(1, &font_texture);
  4766         glGenTextures(1, &font_texture);
  4765         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);
  4766         GLint tex_width = qt_next_power_of_two(tex_height*30); // ###
  4768         GLint tex_width = qt_next_power_of_two(tex_height*30); // ###
  4767         GLint max_tex_size;
  4769         GLint max_tex_size;
  4768         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
  4770         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
  4769         Q_ASSERT(max_tex_size > 0);
  4771         Q_ASSERT(max_tex_size > 0);
  4770         if (tex_width > max_tex_size)
  4772         if (tex_width > max_tex_size)
  4782     } else {
  4784     } else {
  4783         font_tex = it.value();
  4785         font_tex = it.value();
  4784         glBindTexture(GL_TEXTURE_2D, font_tex->texture);
  4786         glBindTexture(GL_TEXTURE_2D, font_tex->texture);
  4785     }
  4787     }
  4786 
  4788 
  4787     for (int i=0; i< glyphs.size(); ++i) {
  4789     for (int i=0; i< numGlyphs; ++i) {
  4788         QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
  4790         QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
  4789         if (it == cache->constEnd()) {
  4791         if (it == cache->constEnd()) {
  4790             // render new glyph and put it in the cache
  4792             // render new glyph and put it in the cache
  4791             glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
  4793             glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]);
  4792             int glyph_width = qRound(metrics.width.toReal())+2;
  4794             int glyph_width = qRound(metrics.width.toReal())+2;
  4793             int glyph_height = qRound(ti.ascent.toReal() + ti.descent.toReal())+2;
  4795             int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2;
  4794 
  4796 
  4795             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) {
  4796                 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);
  4797                 font_tex->x_offset = x_margin;
  4799                 font_tex->x_offset = x_margin;
  4798                 font_tex->y_offset += strip_height;
  4800                 font_tex->y_offset += strip_height;
  4799                 if (font_tex->y_offset >= font_tex->height) {
  4801                 if (font_tex->y_offset >= font_tex->height) {
  4800                     // get hold of the old font texture
  4802                     // get hold of the old font texture
  4801                     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);
  4824                         ++it;
  4826                         ++it;
  4825                     }
  4827                     }
  4826                 }
  4828                 }
  4827             }
  4829             }
  4828 
  4830 
  4829             QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i]));
  4831             QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i]));
  4830             glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
  4832             glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8);
  4831             glyph_width = glyph_im.width();
  4833             glyph_width = glyph_im.width();
  4832             Q_ASSERT(glyph_width >= 0);
  4834             Q_ASSERT(glyph_width >= 0);
  4833             // pad the glyph width to an even number
  4835             // pad the glyph width to an even number
  4834             if (glyph_width%2 != 0)
  4836             if (glyph_width%2 != 0)
  4904 void qgl_cleanup_glyph_cache(QGLContext *ctx)
  4906 void qgl_cleanup_glyph_cache(QGLContext *ctx)
  4905 {
  4907 {
  4906     qt_glyph_cache()->cleanupContext(ctx);
  4908     qt_glyph_cache()->cleanupContext(ctx);
  4907 }
  4909 }
  4908 
  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 
  4909 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
  4980 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
  4910 {
  4981 {
  4911     Q_D(QOpenGLPaintEngine);
  4982     Q_D(QOpenGLPaintEngine);
  4912 
  4983 
  4913     const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
  4984     const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
  4918                                   && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
  4989                                   && d->pen_brush_style <= Qt::ConicalGradientPattern)) {
  4919         QPaintEngine::drawTextItem(p, textItem);
  4990         QPaintEngine::drawTextItem(p, textItem);
  4920         return;
  4991         return;
  4921     }
  4992     }
  4922 
  4993 
  4923     d->flushDrawQueue();
       
  4924 
       
  4925     // add the glyphs used to the glyph texture cache
  4994     // add the glyphs used to the glyph texture cache
  4926     QVarLengthArray<QFixedPoint> positions;
  4995     QVarLengthArray<QFixedPoint> positions;
  4927     QVarLengthArray<glyph_t> glyphs;
  4996     QVarLengthArray<glyph_t> glyphs;
  4928     QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y()));
  4997     QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y()));
  4929     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
  4998     ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
  4930 
  4999 
  4931     // make sure the glyphs we want to draw are in the cache
  5000     {
  4932     qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs);
  5001         QStaticTextItem staticTextItem;
  4933 
  5002         staticTextItem.chars = ti.chars;
  4934     d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops
  5003         staticTextItem.fontEngine = ti.fontEngine;
  4935     qt_glColor4ubv(d->pen_color);
  5004         staticTextItem.glyphs = glyphs.data();
  4936     glEnable(GL_TEXTURE_2D);
  5005         staticTextItem.numChars = ti.num_chars;
  4937 
  5006         staticTextItem.numGlyphs = glyphs.size();
  4938 #ifdef Q_WS_QWS
  5007         staticTextItem.glyphPositions = positions.data();
  4939     // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want
  5008         drawStaticTextItem(&staticTextItem);
  4940     // text rendering to update the alpha in the window surface.
  5009     }
  4941     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
  5010 
  4942     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
       
  4943 #endif
       
  4944 
       
  4945     // do the actual drawing
       
  4946     q_vertexType vertexArray[4*2];
       
  4947     q_vertexType texCoordArray[4*2];
       
  4948 
       
  4949     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
       
  4950     glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
       
  4951 
       
  4952     glEnableClientState(GL_VERTEX_ARRAY);
       
  4953     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4954     bool antialias = !(ti.fontEngine->fontDef.styleStrategy & QFont::NoAntialias)
       
  4955                    && (d->matrix.type() > QTransform::TxTranslate);
       
  4956     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4957     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST);
       
  4958 
       
  4959     for (int i=0; i< glyphs.size(); ++i) {
       
  4960         QGLGlyphCoord *g = qt_glyph_cache()->lookup(ti.fontEngine, glyphs[i]);
       
  4961 
       
  4962         // we don't cache glyphs with no width/height
       
  4963         if (!g)
       
  4964             continue;
       
  4965 
       
  4966         qreal x1, x2, y1, y2;
       
  4967         x1 = g->x;
       
  4968         y1 = g->y;
       
  4969         x2 = x1 + g->width;
       
  4970         y2 = y1 + g->height;
       
  4971 
       
  4972         QPointF logical_pos((positions[i].x - g->x_offset).toReal(),
       
  4973                             (positions[i].y + g->y_offset).toReal());
       
  4974 
       
  4975         qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray);
       
  4976         qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray);
       
  4977 
       
  4978         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
       
  4979     }
       
  4980 
       
  4981     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
       
  4982     glDisableClientState(GL_VERTEX_ARRAY);
       
  4983 
       
  4984     glDisable(GL_TEXTURE_2D);
       
  4985 
       
  4986 #ifdef Q_WS_QWS
       
  4987     // XXX: This may not be needed as this behavior does seem to be caused by driver bug
       
  4988     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
       
  4989 #endif
       
  4990 }
  5011 }
  4991 
  5012 
  4992 
  5013 
  4993 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect)
  5014 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect)
  4994 {
  5015 {
  5158 {
  5179 {
  5159 #ifdef Q_WS_QWS
  5180 #ifdef Q_WS_QWS
  5160     Q_UNUSED(rect);
  5181     Q_UNUSED(rect);
  5161     Q_UNUSED(maskOffset);
  5182     Q_UNUSED(maskOffset);
  5162 #else
  5183 #else
  5163     q_vertexType vertexArray[8];
  5184     GLfloat vertexArray[8];
  5164     qt_add_rect_to_array(rect, vertexArray);
  5185     qt_add_rect_to_array(rect, vertexArray);
  5165 
  5186 
  5166     composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset);
  5187     composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset);
  5167 #endif
  5188 #endif
  5168 }
  5189 }
  5169 
  5190 
  5170 
  5191 
  5171 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)
  5172 {
  5193 {
  5173 #ifdef QT_OPENGL_ES
  5194 #ifdef QT_OPENGL_ES
  5174     Q_UNUSED(primitive);
  5195     Q_UNUSED(primitive);
  5175     Q_UNUSED(vertexArray);
  5196     Q_UNUSED(vertexArray);
  5176     Q_UNUSED(vertexCount);
  5197     Q_UNUSED(vertexCount);
  5189         q->updateCompositionMode(composition_mode);
  5210         q->updateCompositionMode(composition_mode);
  5190     else {
  5211     else {
  5191         qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
  5212         qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9;
  5192 
  5213 
  5193         for (int i = 0; i < vertexCount; ++i) {
  5214         for (int i = 0; i < vertexCount; ++i) {
  5194             qreal x = vt2f(vertexArray[2 * i]);
  5215             qreal x = vertexArray[2 * i];
  5195             qreal y = vt2f(vertexArray[2 * i + 1]);
  5216             qreal y = vertexArray[2 * i + 1];
  5196 
  5217 
  5197             qreal tx, ty;
  5218             qreal tx, ty;
  5198             matrix.map(x, y, &tx, &ty);
  5219             matrix.map(x, y, &tx, &ty);
  5199 
  5220 
  5200             minX = qMin(minX, tx);
  5221             minX = qMin(minX, tx);
  5249 
  5270 
  5250         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform);
  5271         updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform);
  5251     }
  5272     }
  5252 
  5273 
  5253     glEnableClientState(GL_VERTEX_ARRAY);
  5274     glEnableClientState(GL_VERTEX_ARRAY);
  5254     glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
  5275     glVertexPointer(2, GL_FLOAT, 0, vertexArray);
  5255     glEnable(GL_FRAGMENT_PROGRAM_ARB);
  5276     glEnable(GL_FRAGMENT_PROGRAM_ARB);
  5256     GLuint program = qt_gl_program_cache()->getProgram(device->context(),
  5277     GLuint program = qt_gl_program_cache()->getProgram(device->context(),
  5257                                                        fragment_brush,
  5278                                                        fragment_brush,
  5258                                                        fragment_composition_mode, false);
  5279                                                        fragment_composition_mode, false);
  5259     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);
  5280     glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program);