PageRenderTime 9ms CodeModel.GetById 1ms app.highlight 66ms RepoModel.GetById 0ms app.codeStats 1ms

/src/threed/painting/qglpainter.cpp

https://bitbucket.org/manctl/qt3d
C++ | 2366 lines | 1308 code | 148 blank | 910 comment | 222 complexity | ec43ac14b87db2d542b2b8f4bf4379f7 MD5 | raw file
Possible License(s): CC-BY-SA-4.0, LGPL-2.1, GPL-3.0, AGPL-3.0, LGPL-3.0
   1/****************************************************************************
   2**
   3** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
   4** Contact: http://www.qt-project.org/
   5**
   6** This file is part of the Qt3D module of the Qt Toolkit.
   7**
   8** $QT_BEGIN_LICENSE:LGPL$
   9** GNU Lesser General Public License Usage
  10** This file may be used under the terms of the GNU Lesser General Public
  11** License version 2.1 as published by the Free Software Foundation and
  12** appearing in the file LICENSE.LGPL included in the packaging of this
  13** file. Please review the following information to ensure the GNU Lesser
  14** General Public License version 2.1 requirements will be met:
  15** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  16**
  17** In addition, as a special exception, Nokia gives you certain additional
  18** rights. These rights are described in the Nokia Qt LGPL Exception
  19** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  20**
  21** GNU General Public License Usage
  22** Alternatively, this file may be used under the terms of the GNU General
  23** Public License version 3.0 as published by the Free Software Foundation
  24** and appearing in the file LICENSE.GPL included in the packaging of this
  25** file. Please review the following information to ensure the GNU General
  26** Public License version 3.0 requirements will be met:
  27** http://www.gnu.org/copyleft/gpl.html.
  28**
  29** Other Usage
  30** Alternatively, this file may be used in accordance with the terms and
  31** conditions contained in a signed written agreement between you and Nokia.
  32**
  33**
  34**
  35**
  36**
  37**
  38** $QT_END_LICENSE$
  39**
  40****************************************************************************/
  41
  42#include "qglpainter.h"
  43#include "qglpainter_p.h"
  44#include "qglabstracteffect.h"
  45#include "qglext_p.h"
  46
  47#include <QOpenGLContext>
  48#include <QOpenGLShaderProgram>
  49#include <QOpenGLFramebufferObject>
  50#include <QPainter>
  51#include <QPaintEngine>
  52#include <QVarLengthArray>
  53#include <QMap>
  54#include <QDebug>
  55
  56#if !defined(QT_NO_THREAD)
  57#include <QThreadStorage>
  58#include <QThread>
  59#endif
  60
  61#include "qglflatcoloreffect_p.h"
  62#include "qglflattextureeffect_p.h"
  63#include "qgllitmaterialeffect_p.h"
  64#include "qgllittextureeffect_p.h"
  65#include "qglpickcolors_p.h"
  66#include "qgltexture2d.h"
  67#include "qgltexturecube.h"
  68#include "qgeometrydata.h"
  69#include "qglvertexbundle_p.h"
  70#include "qmatrix4x4stack_p.h"
  71#include "qglwindowsurface.h"
  72#include "qglpaintersurface_p.h"
  73
  74#undef glActiveTexture
  75
  76QT_BEGIN_NAMESPACE
  77
  78/*!
  79    \class QGLPainter
  80    \brief The QGLPainter class provides portable API's for rendering into a GL context.
  81    \since 4.8
  82    \ingroup qt3d
  83    \ingroup qt3d::painting
  84
  85    TBD - lots of TBD
  86
  87    All QGLPainter instances on a context share the same context state:
  88    matrices, effects, vertex attributes, etc.  For example, calling
  89    ortho() on one QGLPainter instance for a context will alter the
  90    projectionMatrix() as seen by the other QGLPainter instances.
  91*/
  92
  93/*!
  94    \enum QGLPainter::Update
  95    This enum defines the values that were changed since the last QGLPainter::update().
  96
  97    \value UpdateColor The color has been updated.
  98    \value UpdateModelViewMatrix The modelview matrix has been updated.
  99    \value UpdateProjectionMatrix The projection matrix has been updated.
 100    \value UpdateMatrices The combination of UpdateModelViewMatrix and
 101           UpdateProjectionMatrix.
 102    \value UpdateLights The lights have been updated.
 103    \value UpdateMaterials The material parameters have been updated.
 104    \value UpdateViewport The viewport needs to be updated because the
 105           drawing surface has changed.
 106    \value UpdateAll All values have been updated.  This is specified
 107           when an effect is activated.
 108*/
 109
 110#define QGLPAINTER_CHECK_PRIVATE() \
 111    Q_ASSERT_X(d, "QGLPainter", "begin() has not been called or it failed")
 112
 113QGLPainterPrivate::QGLPainterPrivate()
 114    : ref(1),
 115      badShaderCount(0),
 116      eye(QGL::NoEye),
 117      lightModel(0),
 118      defaultLightModel(0),
 119      defaultLight(0),
 120      frontMaterial(0),
 121      backMaterial(0),
 122      defaultMaterial(0),
 123      frontColorMaterial(0),
 124      backColorMaterial(0),
 125      viewingCube(QVector3D(-1, -1, -1), QVector3D(1, 1, 1)),
 126      color(255, 255, 255, 255),
 127      updates(QGLPainter::UpdateAll),
 128      pick(0),
 129      boundVertexBuffer(0),
 130      boundIndexBuffer(0),
 131      renderSequencer(0),
 132      isFixedFunction(true) // Updated by QGLPainter::begin()
 133{
 134    context = 0;
 135    effect = 0;
 136    userEffect = 0;
 137    standardEffect = QGL::FlatColor;
 138    memset(stdeffects, 0, sizeof(stdeffects));
 139}
 140
 141QGLPainterPrivate::~QGLPainterPrivate()
 142{
 143    delete defaultLightModel;
 144    delete defaultLight;
 145    delete defaultMaterial;
 146    delete frontColorMaterial;
 147    delete backColorMaterial;
 148    for (int effect = 0; effect < QGL_MAX_STD_EFFECTS; ++effect)
 149        delete stdeffects[effect];
 150    delete pick;
 151    qDeleteAll(cachedPrograms);
 152    delete renderSequencer;
 153}
 154
 155QGLPainterPickPrivate::QGLPainterPickPrivate()
 156{
 157    isPicking = false;
 158    objectPickId = -1;
 159    pickColorIndex = -1;
 160    pickColor = 0;
 161    defaultPickEffect = new QGLFlatColorEffect();
 162}
 163
 164QGLPainterPickPrivate::~QGLPainterPickPrivate()
 165{
 166    delete defaultPickEffect;
 167}
 168
 169#if !defined(QT_NO_THREAD)
 170
 171// QOpenGLContext's are thread-specific, so QGLPainterPrivateCache should be too.
 172
 173typedef QThreadStorage<QGLPainterPrivateCache *> QGLPainterPrivateStorage;
 174Q_GLOBAL_STATIC(QGLPainterPrivateStorage, painterPrivateStorage)
 175static QGLPainterPrivateCache *painterPrivateCache()
 176{
 177    QGLPainterPrivateCache *cache = painterPrivateStorage()->localData();
 178    if (!cache) {
 179        cache = new QGLPainterPrivateCache();
 180        painterPrivateStorage()->setLocalData(cache);
 181    }
 182    return cache;
 183}
 184
 185#else
 186
 187Q_GLOBAL_STATIC(QGLPainterPrivateCache, painterPrivateCache)
 188
 189#endif
 190
 191QGLPainterPrivateCache::QGLPainterPrivateCache()
 192{
 193}
 194
 195QGLPainterPrivateCache::~QGLPainterPrivateCache()
 196{
 197}
 198
 199QGLPainterPrivate *QGLPainterPrivateCache::fromContext(QOpenGLContext *context)
 200{
 201    QGLPainterPrivate *priv = cache.value(context, 0);
 202    if (priv)
 203        return priv;
 204#ifndef QT_NO_THREAD
 205    Q_ASSERT_X(context->thread() == QThread::currentThread(),
 206               Q_FUNC_INFO,
 207               "Attempt to fetch painter state for context outside contexts thread");
 208#endif
 209    // since we assert this is the same thread then this is bound to be a direct
 210    // connection, not a queued (asynchronous) connection
 211    connect(context, SIGNAL(destroyed()), this, SLOT(contextDestroyed()));
 212    priv = new QGLPainterPrivate();
 213    priv->context = context;
 214    cache.insert(context, priv);
 215    return priv;
 216}
 217
 218QGLPainterPrivateCache *QGLPainterPrivateCache::instance()
 219{
 220    return painterPrivateCache();
 221}
 222
 223void QGLPainterPrivateCache::contextDestroyed()
 224{
 225    QOpenGLContext *context = qobject_cast<QOpenGLContext *>(sender());
 226    QGLPainterPrivate *priv = cache.value(context, 0);
 227    if (priv) {
 228        priv->context = 0;
 229        cache.remove(context);
 230        if (!priv->ref.deref())
 231            delete priv;
 232    }
 233    emit destroyedContext(context);
 234}
 235
 236/*!
 237    Constructs a new GL painter.  Call begin() to attach the
 238    painter to a GL context.
 239
 240    \sa begin()
 241*/
 242QGLPainter::QGLPainter()
 243    : d_ptr(0)
 244{
 245}
 246
 247/*!
 248    Constructs a new GL painter and attaches it to \a context.
 249    It is not necessary to call begin() after construction.
 250
 251    \sa begin()
 252*/
 253QGLPainter::QGLPainter(QOpenGLContext *context)
 254    : d_ptr(0)
 255{
 256    begin(context);
 257}
 258
 259/*!
 260    Constructs a new GL painter and attaches it to the GL
 261    context associated with \a window.  It is not necessary to
 262    call begin() after construction.
 263
 264    \sa begin(), isActive()
 265*/
 266QGLPainter::QGLPainter(QWindow *window)
 267    : d_ptr(0)
 268{
 269    begin(window);
 270}
 271
 272/*!
 273    Constructs a new GL painter and attaches it to the GL context associated
 274    with \a painter.  It is assumed that \a painter is the currently
 275    active painter and that it is associated with the current GL context.
 276
 277    If \a painter is not using an OpenGL paint engine, then isActive()
 278    will return false; true otherwise.
 279
 280    This constructor is typically used when mixing regular Qt painting
 281    operations and GL painting operations on a widget that is being
 282    drawn using the OpenGL graphics system.
 283
 284    \sa begin(), isActive()
 285*/
 286QGLPainter::QGLPainter(QPainter *painter)
 287    : d_ptr(0)
 288{
 289    begin(painter);
 290}
 291
 292/*!
 293    Constructs a new GL painter and attaches it to the GL context associated
 294    with \a surface.
 295
 296    \sa begin(), isActive()
 297*/
 298QGLPainter::QGLPainter(QGLAbstractSurface *surface)
 299    : d_ptr(0)
 300{
 301    begin(surface);
 302}
 303
 304/*!
 305    Destroys this GL painter.
 306*/
 307QGLPainter::~QGLPainter()
 308{
 309    end();
 310}
 311
 312/*!
 313    Begins painting on the current GL context.  Returns false
 314    if there is no GL context current.
 315
 316    \sa end()
 317*/
 318bool QGLPainter::begin()
 319{
 320    return begin(QOpenGLContext::currentContext());
 321}
 322
 323/*!
 324    Begins painting on \a context.  If painting was already in progress,
 325    then this function will call end() first.  The \a context will be
 326    made current if it is not already current.
 327
 328    Returns true if painting can begin; false otherwise.
 329
 330    All QGLPainter instances on a context share the same context state:
 331    matrices, the effect(), vertex attributes, etc.  For example,
 332    calling ortho() on one QGLPainter instance for a context will
 333    alter the projectionMatrix() as seen by the other QGLPainter instances.
 334
 335    \sa end(), isActive()
 336*/
 337bool QGLPainter::begin(QOpenGLContext *context)
 338{
 339    if (!context)
 340        return false;
 341    end();
 342    return begin(context, QGLAbstractSurface::createSurfaceForContext(context));
 343}
 344
 345/*!
 346    \internal
 347*/
 348bool QGLPainter::begin
 349    (QOpenGLContext *context, QGLAbstractSurface *surface,
 350     bool destroySurface)
 351{
 352    // If we don't have a context specified, then use the one
 353    // that the surface just made current.
 354    if (!context)
 355        context = QOpenGLContext::currentContext();
 356
 357    if (!context)
 358    {
 359        qWarning() << "##### Attempt to begin painter with no GL context!";
 360        return false;
 361    }
 362
 363    // Initialize the QOpenGLFunctions parent class.
 364    initializeGLFunctions();
 365
 366    // Determine if the OpenGL implementation is fixed-function or not.
 367    bool isFixedFunction = !hasOpenGLFeature(QOpenGLFunctions::Shaders);
 368    if (!isFixedFunction)
 369        isFixedFunction = !QOpenGLShaderProgram::hasOpenGLShaderPrograms();
 370    if (!isFixedFunction)
 371    {
 372        QOpenGLContext *ctx = QOpenGLContext::currentContext();
 373        QFunctionPointer res = ctx->getProcAddress("glCreateShader");
 374        if (!res)
 375        {
 376            res = ctx->getProcAddress("glCreateShaderObject");
 377            if (!res)
 378            {
 379                res = ctx->getProcAddress("glCreateShaderObjectARB");
 380            }
 381        }
 382        if (!res)
 383            isFixedFunction = !res;
 384    }
 385
 386    // Find the QGLPainterPrivate for the context, or create a new one.
 387    d_ptr = painterPrivateCache()->fromContext(context);
 388    d_ptr->ref.ref();
 389    d_ptr->isFixedFunction = isFixedFunction;
 390    if (d_ptr->renderSequencer)
 391    {
 392        d_ptr->renderSequencer->reset();
 393        d_ptr->renderSequencer->setPainter(this);
 394    }
 395
 396    // Activate the main surface for the context.
 397    QGLAbstractSurface *prevSurface;
 398    if (d_ptr->surfaceStack.isEmpty()) {
 399        prevSurface = 0;
 400    } else {
 401        // We are starting a nested begin()/end() scope, so switch
 402        // to the new main surface rather than activate from scratch.
 403        prevSurface = d_ptr->surfaceStack.last().surface;
 404        prevSurface->deactivate(surface);
 405    }
 406    if (!surface->activate(prevSurface)) {
 407        if (prevSurface)
 408            prevSurface->activate(surface);
 409        if (destroySurface)
 410            delete surface;
 411        if (!d_ptr->ref.deref())
 412            delete d_ptr;
 413        d_ptr = 0;
 414        return false;
 415    }
 416
 417    // Push a main surface descriptor onto the surface stack.
 418    QGLPainterSurfaceInfo psurf;
 419    psurf.surface = surface;
 420    psurf.destroySurface = destroySurface;
 421    psurf.mainSurface = true;
 422    d_ptr->surfaceStack.append(psurf);
 423
 424    // Force the matrices to be updated the first time we use them.
 425    d_ptr->modelViewMatrix.setDirty(true);
 426    d_ptr->projectionMatrix.setDirty(true);
 427
 428    return true;
 429}
 430
 431/*!
 432    Begins GL painting on \a widget.  Returns false if \a widget is null.
 433
 434    \sa end()
 435*/
 436bool QGLPainter::begin(QWindow *window)
 437{
 438    bool result = false;
 439    if (window)
 440    {
 441        end();
 442        result = begin(0, new QGLWindowSurface(window));
 443    }
 444    return result;
 445}
 446
 447/*!
 448    Begins painting on the GL context associated with \a painter.
 449    Returns false if \a painter is not using an OpenGL paint engine.
 450    It is assumed that \a painter is the currently active painter
 451    and that it is associated with the current GL context.
 452
 453    This function is typically used when mixing regular Qt painting
 454    operations and GL painting operations on a widget that is being
 455    drawn using the OpenGL graphics system.
 456
 457    \sa end()
 458*/
 459bool QGLPainter::begin(QPainter *painter)
 460{
 461    // Validate that the painting is OpenGL-based.
 462    if (!painter)
 463        return false;
 464    QPaintEngine *engine = painter->paintEngine();
 465    if (!engine)
 466        return false;
 467    if (engine->type() != QPaintEngine::OpenGL &&
 468            engine->type() != QPaintEngine::OpenGL2)
 469        return false;
 470
 471    // Begin GL painting operations.
 472    return begin(0, new QGLPainterSurface(painter));
 473}
 474
 475/*!
 476    Begins painting to \a surface.  Returns false if \a surface is
 477    null or could not be activated.
 478
 479    \sa end(), QGLAbstractSurface::activate()
 480*/
 481bool QGLPainter::begin(QGLAbstractSurface *surface)
 482{
 483    if (!surface)
 484        return false;
 485    end();
 486    return begin(0, surface, false);
 487}
 488
 489/*!
 490    Ends GL painting.  Returns true if painting was ended successfully;
 491    false if this painter was not bound to a GL context.
 492
 493    The GL context that was bound to this painter will not have
 494    QOpenGLContext::doneCurrent() called on it.  It is the responsibility
 495    of the caller to terminate context operations.
 496
 497    The effect() will be left active in the GL context and will be
 498    assumed to still be active the next time begin() is called.
 499    If this assumption doesn't apply, then call disableEffect()
 500    to disable the effect before calling end().
 501
 502    This function will pop all surfaces from the surface stack,
 503    and return currentSurface() to null (the default drawing surface).
 504
 505    \sa begin(), isActive(), disableEffect()
 506*/
 507bool QGLPainter::end()
 508{
 509    Q_D(QGLPainter);
 510    if (!d)
 511        return false;
 512
 513    // Unbind the current vertex and index buffers.
 514    if (d->boundVertexBuffer) {
 515        QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
 516        d->boundVertexBuffer = 0;
 517    }
 518    if (d->boundIndexBuffer) {
 519        QOpenGLBuffer::release(QOpenGLBuffer::IndexBuffer);
 520        d->boundIndexBuffer = 0;
 521    }
 522
 523    // Pop surfaces from the surface stack until we reach a
 524    // main surface.  Then deactivate the main surface.
 525    int size = d->surfaceStack.size();
 526    while (size > 0) {
 527        --size;
 528        QGLPainterSurfaceInfo &surf = d->surfaceStack[size];
 529        if (surf.mainSurface) {
 530            if (size > 0) {
 531                // There are still other surfaces on the stack, probably
 532                // because we are within a nested begin()/end() scope.
 533                // Re-activate the next surface down in the outer scope.
 534                QGLPainterSurfaceInfo &nextSurf = d->surfaceStack[size - 1];
 535                surf.surface->switchTo(nextSurf.surface);
 536            } else {
 537                // Last surface on the stack, so deactivate it permanently.
 538                surf.surface->deactivate();
 539            }
 540            if (surf.destroySurface)
 541                delete surf.surface;
 542            break;
 543        } else if (size > 0) {
 544            surf.surface->deactivate(d->surfaceStack[size - 1].surface);
 545        }
 546    }
 547    d->surfaceStack.resize(size);
 548
 549    // Force a viewport update if we are within a nested begin()/end().
 550    d->updates |= UpdateViewport;
 551
 552    // Destroy the QGLPainterPrivate if this is the last reference.
 553    if (!d->ref.deref())
 554        delete d;
 555    d_ptr = 0;
 556    return true;
 557}
 558
 559/*!
 560    Returns true if this painter is currently bound to a GL context;
 561    false otherwise.
 562
 563    \sa begin(), end()
 564*/
 565bool QGLPainter::isActive() const
 566{
 567    return (d_ptr != 0 && d_ptr->context != 0);
 568}
 569
 570/*!
 571    Returns the GL context that is bound to this painter, or null
 572    if it is not currently bound.
 573*/
 574QOpenGLContext *QGLPainter::context() const
 575{
 576    if (d_ptr)
 577        return d_ptr->context;
 578    else
 579        return 0;
 580}
 581
 582/*!
 583    Returns true if the underlying OpenGL implementation is OpenGL 1.x
 584    or OpenGL/ES 1.x and only supports fixed-function OpenGL operations.
 585    Returns false if the underlying OpenGL implementation is using
 586    GLSL or GLSL/ES shaders.
 587
 588    If this function returns false, then the built-in effects will
 589    use shaders and QGLPainter will not update the fixed-function
 590    matrices in the OpenGL context when update() is called.
 591    User-supplied effects will need to use shaders also or update
 592    the fixed-function matrices themselves or call updateFixedFunction().
 593
 594    \sa update(), updateFixedFunction()
 595*/
 596bool QGLPainter::isFixedFunction() const
 597{
 598#if defined(QT_OPENGL_ES_2)
 599    return false;
 600#else
 601    Q_D(const QGLPainter);
 602    if (d)
 603        return d->isFixedFunction;
 604    else
 605        return true;
 606#endif
 607}
 608
 609/*!
 610    Sets the \a color to use to clear the color buffer when \c{glClear()}
 611    is called.
 612*/
 613void QGLPainter::setClearColor(const QColor& color)
 614{
 615    glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
 616}
 617
 618/*!
 619    Sets the scissor \a rect for the current drawing surface
 620    to use when \c{GL_SCISSOR_TEST} is enabled.  If \a rect is empty,
 621    then the scissor will be set to clip away all drawing.
 622
 623    Note that \a rect is in Qt co-ordinates with the origin
 624    at the top-left of the drawing surface's viewport rectangle.
 625    If the currentSurface() is an instance of QGLSubsurface,
 626    then \a rect will be adjusted relative to the subsurface's position.
 627
 628    \sa currentSurface(), QGLAbstractSurface::viewportGL()
 629*/
 630void QGLPainter::setScissor(const QRect& rect)
 631{
 632    if (!rect.isEmpty()) {
 633        // Adjust the rectangle by the position of the surface viewport.
 634        QGLAbstractSurface *surface = currentSurface();
 635        QRect viewport = surface->viewportGL();
 636        QRect r(viewport.x() + rect.x(),
 637                viewport.y() + viewport.height() - (rect.y() + rect.height()),
 638                rect.width(), rect.height());
 639        if (!r.isEmpty())
 640            glScissor(r.x(), r.y(), r.width(), r.height());
 641        else
 642            glScissor(0, 0, 0, 0);
 643    } else {
 644        glScissor(0, 0, 0, 0);
 645    }
 646}
 647
 648/*!
 649    Returns a reference to the projection matrix stack.
 650
 651    It is recommended that setCamera() be used to set the projection
 652    matrix at the beginning of a scene rendering pass so that the
 653    eye position can be adjusted for stereo.
 654
 655    \sa modelViewMatrix(), combinedMatrix(), setCamera()
 656*/
 657QMatrix4x4Stack& QGLPainter::projectionMatrix()
 658{
 659    Q_D(QGLPainter);
 660    QGLPAINTER_CHECK_PRIVATE();
 661    return d->projectionMatrix;
 662}
 663
 664/*!
 665    Returns a reference to the modelview matrix stack.
 666
 667    \sa projectionMatrix(), combinedMatrix(), normalMatrix(), setCamera()
 668    \sa worldMatrix()
 669*/
 670QMatrix4x4Stack& QGLPainter::modelViewMatrix()
 671{
 672    Q_D(QGLPainter);
 673    QGLPAINTER_CHECK_PRIVATE();
 674    return d->modelViewMatrix;
 675}
 676
 677/*!
 678    \fn QMatrix4x4 QGLPainter::combinedMatrix() const
 679
 680    Returns the result of multiplying the projectionMatrix()
 681    and the modelViewMatrix().  This combined matrix value is
 682    useful for setting uniform matrix values on shader programs.
 683
 684    Calling this function is more efficient than calling
 685    projectionMatrix() and modelViewMatrix() separately and
 686    multiplying the return values.
 687
 688    \sa projectionMatrix(), modelViewMatrix(), normalMatrix()
 689*/
 690QMatrix4x4 QGLPainter::combinedMatrix() const
 691{
 692    const QGLPainterPrivate *d = d_func();
 693    if (!d)
 694        return QMatrix4x4();
 695    const QMatrix4x4StackPrivate *proj = d->projectionMatrix.d_func();
 696    const QMatrix4x4StackPrivate *mv = d->modelViewMatrix.d_func();
 697    return proj->matrix * mv->matrix;
 698}
 699
 700// Inverting the eye transformation will often result in values like
 701// 1.5e-15 in the world matrix.  Clamp these to zero to make worldMatrix()
 702// more stable when removing the eye component of the modelViewMatrix().
 703static inline qreal qt_gl_stablize_value(qreal value)
 704{
 705    return (qAbs(value) >= 0.00001f) ? value : 0.0f;
 706}
 707static inline QMatrix4x4 qt_gl_stablize_matrix(const QMatrix4x4 &m)
 708{
 709    return QMatrix4x4(qt_gl_stablize_value(m(0, 0)),
 710                      qt_gl_stablize_value(m(0, 1)),
 711                      qt_gl_stablize_value(m(0, 2)),
 712                      qt_gl_stablize_value(m(0, 3)),
 713                      qt_gl_stablize_value(m(1, 0)),
 714                      qt_gl_stablize_value(m(1, 1)),
 715                      qt_gl_stablize_value(m(1, 2)),
 716                      qt_gl_stablize_value(m(1, 3)),
 717                      qt_gl_stablize_value(m(2, 0)),
 718                      qt_gl_stablize_value(m(2, 1)),
 719                      qt_gl_stablize_value(m(2, 2)),
 720                      qt_gl_stablize_value(m(2, 3)),
 721                      qt_gl_stablize_value(m(3, 0)),
 722                      qt_gl_stablize_value(m(3, 1)),
 723                      qt_gl_stablize_value(m(3, 2)),
 724                      qt_gl_stablize_value(m(3, 3)));
 725}
 726
 727/*!
 728    Returns the world matrix, which is the modelViewMatrix() without
 729    the eye transformation that was set in the previous call to
 730    setCamera().
 731
 732    In the following example, the \c{world} variable will be set to the
 733    translation and scale component of the modelview transformation,
 734    without the "look at" component from the camera:
 735
 736    \code
 737    painter.setCamera(camera);
 738    painter.modelViewMatrix().translate(0.0f, 5.0f, 0.0f);
 739    painter.modelViewMatrix().scale(1.5f);
 740    QMatrix4x4 world = painter.worldMatrix();
 741    \endcode
 742
 743    Note: the world matrix is determined by multiplying the inverse of
 744    the camera's look at component with the current modelview matrix.
 745    Thus, the result may not be precisely the same as constructing a
 746    matrix from translate and scale operations starting with the identity.
 747
 748    \sa modelViewMatrix(), setCamera()
 749*/
 750QMatrix4x4 QGLPainter::worldMatrix() const
 751{
 752    Q_D(const QGLPainter);
 753    QGLPAINTER_CHECK_PRIVATE();
 754    return qt_gl_stablize_matrix
 755        (d->inverseEyeMatrix * d->modelViewMatrix.top());
 756}
 757
 758/*!
 759    \fn QMatrix3x3 QGLPainter::normalMatrix() const
 760
 761    Returns the normal matrix corresponding to modelViewMatrix().
 762
 763    The normal matrix is the transpose of the inverse of the top-left
 764    3x3 part of the 4x4 modelview matrix.  If the 3x3 sub-matrix is not
 765    invertible, this function returns the identity.
 766
 767    \sa modelViewMatrix(), combinedMatrix()
 768*/
 769QMatrix3x3 QGLPainter::normalMatrix() const
 770{
 771    const QGLPainterPrivate *d = d_func();
 772    if (!d)
 773        return QMatrix3x3();
 774    const QMatrix4x4StackPrivate *mv = d->modelViewMatrix.d_func();
 775    return mv->matrix.normalMatrix();
 776}
 777
 778/*!
 779    Returns the camera eye that is currently being used for stereo
 780    rendering.  The default is QGL::NoEye.
 781
 782    The eye is used to adjust the camera position by a small amount
 783    when setCamera() is called.
 784
 785    \sa setEye(), setCamera()
 786*/
 787QGL::Eye QGLPainter::eye() const
 788{
 789    Q_D(const QGLPainter);
 790    QGLPAINTER_CHECK_PRIVATE();
 791    return d->eye;
 792}
 793
 794/*!
 795    Sets the camera \a eye that is currently being used for stereo
 796    rendering.
 797
 798    The \a eye is used to adjust the camera position by a small amount
 799    when setCamera() is called.
 800
 801    \sa eye(), setCamera()
 802*/
 803void QGLPainter::setEye(QGL::Eye eye)
 804{
 805    Q_D(QGLPainter);
 806    QGLPAINTER_CHECK_PRIVATE();
 807    d->eye = eye;
 808}
 809
 810/*!
 811    Sets the modelViewMatrix() and projectionMatrix() to the view
 812    defined by \a camera.  If eye() is not QGL::NoEye, then the view
 813    will be adjusted for the camera's eye separation.
 814
 815    This function is typically called at the beginning of a scene rendering
 816    pass to initialize the modelview and projection matrices.
 817
 818    Note that this does not cause the painter to take ownership of the camera
 819    and it does not save the pointer value.  The \a camera may be safely
 820    deleted after calling this function.
 821
 822    \sa eye(), modelViewMatrix(), projectionMatrix(), worldMatrix()
 823*/
 824void QGLPainter::setCamera(const QGLCamera *camera)
 825{
 826    Q_ASSERT(camera);
 827    Q_D(QGLPainter);
 828    QGLPAINTER_CHECK_PRIVATE();
 829    QMatrix4x4 lookAt = camera->modelViewMatrix(d->eye);
 830    d->modelViewMatrix = lookAt;
 831    d->projectionMatrix = camera->projectionMatrix(aspectRatio());
 832    d->inverseEyeMatrix = lookAt.inverted();
 833}
 834
 835/*!
 836    Returns true if \a point is outside the current viewing volume.
 837    This is used to perform object culling checks.
 838*/
 839bool QGLPainter::isCullable(const QVector3D& point) const
 840{
 841    Q_D(const QGLPainter);
 842    QGLPAINTER_CHECK_PRIVATE();
 843    QVector3D projected = d->modelViewMatrix * point;
 844    projected = d->projectionMatrix * projected;
 845    return !d->viewingCube.contains(projected);
 846}
 847
 848static inline uint outcode(const QVector4D &v)
 849{
 850    // For a discussion of outcodes see pg 388 Dunn & Parberry.
 851    // For why you can't just test if the point is in a bounding box
 852    // consider the case where a view frustum with view-size 1.5 x 1.5
 853    // is tested against a 2x2 box which encloses the near-plane, while
 854    // all the points in the box are outside the frustum.
 855    // TODO: optimise this with assembler - according to D&P this can
 856    // be done in one line of assembler on some platforms
 857    uint code = 0;
 858    if (v.x() < -v.w()) code |= 0x01;
 859    if (v.x() > v.w())  code |= 0x02;
 860    if (v.y() < -v.w()) code |= 0x04;
 861    if (v.y() > v.w())  code |= 0x08;
 862    if (v.z() < -v.w()) code |= 0x10;
 863    if (v.z() > v.w())  code |= 0x20;
 864    return code;
 865}
 866
 867/*!
 868    Returns true if \a box is completely outside the current viewing volume.
 869    This is used to perform object culling checks.
 870*/
 871bool QGLPainter::isCullable(const QBox3D& box) const
 872{
 873    Q_D(const QGLPainter);
 874    QGLPAINTER_CHECK_PRIVATE();
 875    // This function uses the technique of view frustum culling known as
 876    // clip space testing.  Since the normal QVector3D representation
 877    // of the points throws away the w value needed, we convert the box
 878    // into a set of 8 points represented as QVector4D's and then apply
 879    // the test.  The test is to transform the points into clip space
 880    // by applying the MV and Proj matrices, then test to see if the 4D
 881    // points are outside the clip space by testing x, y & z against w.
 882    QArray<QVector4D> box4d;
 883    QVector3D n = box.minimum();
 884    QVector3D x = box.maximum();
 885    box4d.append(QVector4D(n.x(), n.y(), x.z(), 1), QVector4D(x.x(), n.y(), x.z(), 1),
 886                 QVector4D(x.x(), x.y(), x.z(), 1), QVector4D(n.x(), x.y(), x.z(), 1));
 887    box4d.append(QVector4D(n.x(), n.y(), n.z(), 1), QVector4D(x.x(), n.y(), n.z(), 1),
 888                 QVector4D(x.x(), x.y(), n.z(), 1), QVector4D(n.x(), x.y(), n.z(), 1));
 889    QMatrix4x4 mvp = d->projectionMatrix.top() * d->modelViewMatrix.top();
 890    for (int i = 0; i < box4d.size(); ++i)
 891    {
 892        box4d[i] = mvp * box4d.at(i);
 893    }
 894    // if the logical AND of all the outcodes is non-zero then the BB is
 895    // definitely outside the view frustum.
 896    uint out = 0xff;
 897    for (int i = 0; i < box4d.size(); ++i)
 898    {
 899        out = out & outcode(box4d.at(i));
 900    }
 901    return out;
 902}
 903
 904/*!
 905    Returns the current render order sequencer.
 906
 907    \sa QGLRenderSequencer
 908*/
 909QGLRenderSequencer *QGLPainter::renderSequencer()
 910{
 911    Q_D(QGLPainter);
 912    if (!d->renderSequencer)
 913        d->renderSequencer = new QGLRenderSequencer(this);
 914    return d->renderSequencer;
 915}
 916
 917/*!
 918    Returns the aspect ratio of the viewport for adjusting projection
 919    transformations.
 920*/
 921qreal QGLPainter::aspectRatio() const
 922{
 923    return currentSurface()->aspectRatio();
 924}
 925
 926/*!
 927    Returns the current effect that is in use, which is userEffect()
 928    if it is not null, or the effect object associated with
 929    standardEffect() otherwise.
 930
 931    If isPicking() is true, then this will return the effect object
 932    that is being used to generate pick colors.
 933
 934    \sa userEffect(), standardEffect(), isPicking()
 935*/
 936QGLAbstractEffect *QGLPainter::effect() const
 937{
 938    Q_D(QGLPainter);
 939    QGLPAINTER_CHECK_PRIVATE();
 940    d->ensureEffect(const_cast<QGLPainter *>(this));
 941    return d->effect;
 942}
 943
 944/*!
 945    Returns the user-defined effect that is being used for drawing
 946    operations, or null if standardEffect() is in use.
 947
 948    \sa setUserEffect(), standardEffect(), effect()
 949*/
 950QGLAbstractEffect *QGLPainter::userEffect() const
 951{
 952    Q_D(QGLPainter);
 953    QGLPAINTER_CHECK_PRIVATE();
 954    return d->userEffect;
 955}
 956
 957/*!
 958    Sets a user-defined \a effect to use for drawing operations
 959    in the current GL context.  If \a effect is null, this will
 960    disable user-defined effects and return to using standardEffect().
 961
 962    \sa effect(), draw(), setStandardEffect()
 963*/
 964void QGLPainter::setUserEffect(QGLAbstractEffect *effect)
 965{
 966    Q_D(QGLPainter);
 967    QGLPAINTER_CHECK_PRIVATE();
 968    if (d->userEffect == effect)
 969        return;
 970    if (d->effect)
 971        d->effect->setActive(this, false);
 972    d->userEffect = effect;
 973    if (effect && (!d->pick || !d->pick->isPicking)) {
 974        d->effect = effect;
 975        d->effect->setActive(this, true);
 976        d->updates = UpdateAll;
 977    } else {
 978        // Revert to the effect associated with standardEffect().
 979        d->effect = 0;
 980        d->ensureEffect(this);
 981    }
 982}
 983
 984/*!
 985    Returns the standard effect to use for rendering fragments in
 986    the current GL context when userEffect() is null.
 987
 988    \sa setStandardEffect(), userEffect()
 989*/
 990QGL::StandardEffect QGLPainter::standardEffect() const
 991{
 992    Q_D(QGLPainter);
 993    QGLPAINTER_CHECK_PRIVATE();
 994    return d->standardEffect;
 995}
 996
 997/*!
 998    Sets a standard \a effect to use for rendering fragments
 999    in the current GL context.  This will also set userEffect()
1000    to null.  If \a effect is an invalid value, then the behavior
1001    of QGL::FlatColor will be used instead.
1002
1003    \sa standardEffect(), setUserEffect()
1004*/
1005void QGLPainter::setStandardEffect(QGL::StandardEffect effect)
1006{
1007    Q_D(QGLPainter);
1008    QGLPAINTER_CHECK_PRIVATE();
1009    if (d->standardEffect == effect && d->effect && d->userEffect == 0)
1010        return;
1011    if (d->effect)
1012        d->effect->setActive(this, false);
1013    d->standardEffect = effect;
1014    d->userEffect = 0;
1015    d->effect = 0;
1016    d->ensureEffect(this);
1017}
1018
1019/*!
1020    Disables the current effect and sets userEffect() to null.
1021    Unlike setUserEffect() this not activate the standardEffect()
1022    until the next time effect() is called.
1023
1024    This function can be used to disable all effect-based drawing
1025    operations prior to performing raw GL calls.  The next time
1026    effect() is called on this QGLPainter, the standardEffect()
1027    will be reactivated.  An effect can also be reactivated by
1028    calling setUserEffect() or setStandardEffect().
1029
1030    \sa userEffect(), standardEffect()
1031*/
1032void QGLPainter::disableEffect()
1033{
1034    Q_D(QGLPainter);
1035    QGLPAINTER_CHECK_PRIVATE();
1036    if (d->effect)
1037        d->effect->setActive(this, false);
1038    d->userEffect = 0;
1039    d->effect = 0;
1040}
1041
1042/*!
1043    Returns the cached shader program associated with \a name; or null
1044    if \a name is not currently associated with a shader program.
1045
1046    \sa setCachedProgram()
1047*/
1048QOpenGLShaderProgram *QGLPainter::cachedProgram(const QString& name) const
1049{
1050    Q_D(const QGLPainter);
1051    QGLPAINTER_CHECK_PRIVATE();
1052    return d->cachedPrograms.value(name, 0);
1053}
1054
1055/*!
1056    Sets the cached shader \a program associated with \a name.
1057
1058    Effect objects can use this function to store pre-compiled
1059    and pre-linked shader programs in the painter for future
1060    use by the same effect.  The \a program will be destroyed
1061    when context() is destroyed.
1062
1063    If \a program is null, then the program associated with \a name
1064    will be destroyed.  If \a name is already present as a cached
1065    program, then it will be replaced with \a program.
1066
1067    Names that start with "\c{qt.}" are reserved for use by Qt's
1068    internal effects.
1069
1070    \sa cachedProgram()
1071*/
1072void QGLPainter::setCachedProgram
1073    (const QString& name, QOpenGLShaderProgram *program)
1074{
1075    Q_D(QGLPainter);
1076    QGLPAINTER_CHECK_PRIVATE();
1077    QOpenGLShaderProgram *current = d->cachedPrograms.value(name, 0);
1078    if (current != program) {
1079        if (program)
1080            d->cachedPrograms[name] = program;
1081        else
1082            d->cachedPrograms.remove(name);
1083        delete current;
1084    }
1085}
1086
1087void QGLPainterPrivate::createEffect(QGLPainter *painter)
1088{
1089    if (userEffect) {
1090        if (!pick || !pick->isPicking) {
1091            effect = userEffect;
1092            effect->setActive(painter, true);
1093            updates = QGLPainter::UpdateAll;
1094            return;
1095        }
1096        if (userEffect->supportsPicking()) {
1097            effect = userEffect;
1098            effect->setActive(painter, true);
1099            updates = QGLPainter::UpdateAll;
1100            return;
1101        }
1102        effect = pick->defaultPickEffect;
1103        effect->setActive(painter, true);
1104        updates = QGLPainter::UpdateAll;
1105        return;
1106    }
1107    if (uint(standardEffect) >= QGL_MAX_STD_EFFECTS)
1108        effect = stdeffects[int(QGL::FlatColor)];
1109    else
1110        effect = stdeffects[int(standardEffect)];
1111    if (!effect) {
1112        switch (standardEffect) {
1113        case QGL::FlatColor: default:
1114            effect = new QGLFlatColorEffect();
1115            break;
1116        case QGL::FlatPerVertexColor:
1117            effect = new QGLPerVertexColorEffect();
1118            break;
1119        case QGL::FlatReplaceTexture2D:
1120            effect = new QGLFlatTextureEffect();
1121            break;
1122        case QGL::FlatDecalTexture2D:
1123            effect = new QGLFlatDecalTextureEffect();
1124            break;
1125        case QGL::LitMaterial:
1126            effect = new QGLLitMaterialEffect();
1127            break;
1128        case QGL::LitDecalTexture2D:
1129            effect = new QGLLitDecalTextureEffect();
1130            break;
1131        case QGL::LitModulateTexture2D:
1132            effect = new QGLLitModulateTextureEffect();
1133            break;
1134        }
1135        if (uint(standardEffect) >= QGL_MAX_STD_EFFECTS)
1136            stdeffects[int(QGL::FlatColor)] = effect;
1137        else
1138            stdeffects[int(standardEffect)] = effect;
1139    }
1140    if (!pick || !pick->isPicking || effect->supportsPicking()) {
1141        effect->setActive(painter, true);
1142    } else {
1143        effect = pick->defaultPickEffect;
1144        effect->setActive(painter, true);
1145    }
1146    updates = QGLPainter::UpdateAll;
1147}
1148
1149/*!
1150    Returns the last color that was set with setColor().  The default
1151    value is (1, 1, 1, 1).
1152
1153    \sa setColor()
1154*/
1155QColor QGLPainter::color() const
1156{
1157    Q_D(QGLPainter);
1158    QGLPAINTER_CHECK_PRIVATE();
1159    return d->color;
1160}
1161
1162/*!
1163    Sets the default fragment \a color for effects associated
1164    with this painter.  This function does not apply the color
1165    to the effect until update() is called.
1166
1167    \sa color(), update()
1168*/
1169void QGLPainter::setColor(const QColor& color)
1170{
1171    Q_D(QGLPainter);
1172    QGLPAINTER_CHECK_PRIVATE();
1173    d->color = color;
1174    d->updates |= UpdateColor;
1175}
1176
1177static void qt_gl_setVertexAttribute(QGL::VertexAttribute attribute, const QGLAttributeValue& value)
1178{
1179#if !defined(QT_OPENGL_ES_2)
1180    switch (attribute) {
1181    case QGL::Position:
1182        glVertexPointer(value.tupleSize(), value.type(),
1183                        value.stride(), value.data());
1184        break;
1185
1186    case QGL::Normal:
1187        if (value.tupleSize() == 3)
1188            glNormalPointer(value.type(), value.stride(), value.data());
1189        break;
1190
1191    case QGL::Color:
1192        glColorPointer(value.tupleSize(), value.type(),
1193                       value.stride(), value.data());
1194        break;
1195
1196#ifdef GL_TEXTURE_COORD_ARRAY
1197    case QGL::TextureCoord0:
1198    case QGL::TextureCoord1:
1199    case QGL::TextureCoord2:
1200    {
1201        int unit = (int)(attribute - QGL::TextureCoord0);
1202        qt_gl_ClientActiveTexture(GL_TEXTURE0 + unit);
1203        glTexCoordPointer(value.tupleSize(), value.type(),
1204                          value.stride(), value.data());
1205        if (unit != 0)  // Stay on unit 0 between requests.
1206            qt_gl_ClientActiveTexture(GL_TEXTURE0);
1207    }
1208    break;
1209#endif
1210
1211    default: break;
1212    }
1213#else
1214    Q_UNUSED(attribute);
1215    Q_UNUSED(value);
1216#endif
1217}
1218
1219/*!
1220    Returns the set of vertex attributes that have been set on the
1221    painter state by setVertexAttribute() and setVertexBundle()
1222    since the last call to clearAttributes().
1223
1224    The most common use for this function is to determine if specific
1225    attributes have been supplied on the painter so as to adjust the
1226    current drawing effect accordingly.  The following example will
1227    use a lit texture effect if texture co-ordinates were provided
1228    in the vertex bundle, or a simple lit material effect if
1229    texture co-ordinates were not provided:
1230
1231    \code
1232    painter.clearAttributes();
1233    painter.setVertexBundle(bundle);
1234    if (painter.attributes().contains(QGL::TextureCoord0))
1235        painter.setStandardEffect(QGL::LitModulateTexture2D);
1236    else
1237        painter.setStandardEffect(QGL::LitMaterial);
1238    \endcode
1239
1240    It is important to clear the attributes before setting the vertex
1241    bundle, so that attributes from a previous bundle will not leak
1242    through.  Multiple vertex bundles may be supplied if they contain
1243    different parts of the same logical piece of geometry.
1244
1245    \sa clearAttributes(), setVertexBundle()
1246*/
1247QGLAttributeSet QGLPainter::attributes() const
1248{
1249    Q_D(const QGLPainter);
1250    QGLPAINTER_CHECK_PRIVATE();
1251    return d->attributeSet;
1252}
1253
1254/*!
1255    Clears the set of vertex attributes that have been set on the
1256    painter state by setVertexAttribute() and setVertexBundle().
1257    See the documentation for attributes() for more information.
1258
1259    \sa attributes()
1260*/
1261void QGLPainter::clearAttributes()
1262{
1263    Q_D(QGLPainter);
1264    QGLPAINTER_CHECK_PRIVATE();
1265    d->attributeSet.clear();
1266}
1267
1268/*!
1269    Sets a vertex \a attribute on the current GL context to \a value.
1270
1271    The vertex attribute is bound to the GL state on the index
1272    corresponding to \a attribute.  For example, QGL::Position
1273    will be bound to index 0, QGL::TextureCoord0 will be bound
1274    to index 3, etc.
1275
1276    Vertex attributes are independent of the effect() and can be
1277    bound once and then used with multiple effects.
1278
1279    If this is the first attribute in a new piece of geometry,
1280    it is recommended that clearAttributes() be called before this
1281    function.  This will inform QGLPainter that a new piece of geometry
1282    is being provided and that the previous geometry is now invalid.
1283    See the documentation for attributes() for more information.
1284
1285    \sa setVertexBundle(), draw(), clearAttributes(), attributes()
1286*/
1287void QGLPainter::setVertexAttribute
1288    (QGL::VertexAttribute attribute, const QGLAttributeValue& value)
1289{
1290    Q_D(QGLPainter);
1291    QGLPAINTER_CHECK_PRIVATE();
1292    d->ensureEffect(this);
1293    if (d->boundVertexBuffer) {
1294        QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1295        d->boundVertexBuffer = 0;
1296    }
1297    if (d->isFixedFunction) {
1298        qt_gl_setVertexAttribute(attribute, value);
1299    } else {
1300        glVertexAttribPointer(GLuint(attribute), value.tupleSize(),
1301                              value.type(), GL_TRUE,
1302                              value.stride(), value.data());
1303    }
1304    d->attributeSet.insert(attribute);
1305}
1306
1307/*!
1308    Sets the vertex attributes on the current GL context that are
1309    stored in \a buffer.
1310
1311    The vertex attributes are bound to the GL state on the indexes
1312    that are specified within \a buffer; QGL::Position will be
1313    bound to index 0, QGL::TextureCoord0 will be bound to index 3, etc.
1314
1315    Vertex attributes are independent of the effect() and can be
1316    bound once and then used with multiple effects.
1317
1318    It is recommended that clearAttributes() be called before this
1319    function to inform QGLPainter that a new piece of geometry is
1320    being provided and that the previous geometry is now invalid.
1321    See the documentation for attributes() for more information.
1322
1323    \sa setVertexAttribute(), draw(), clearAttributes(), attributes()
1324*/
1325void QGLPainter::setVertexBundle(const QGLVertexBundle& buffer)
1326{
1327    Q_D(QGLPainter);
1328    QGLPAINTER_CHECK_PRIVATE();
1329    d->ensureEffect(this);
1330    QGLVertexBundlePrivate *bd = const_cast<QGLVertexBundlePrivate *>(buffer.d_func());
1331    if (bd->buffer.isCreated()) {
1332        GLuint id = bd->buffer.bufferId();
1333        if (id != d->boundVertexBuffer) {
1334            bd->buffer.bind();
1335            d->boundVertexBuffer = id;
1336        }
1337    } else if (d->boundVertexBuffer) {
1338        QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1339        d->boundVertexBuffer = 0;
1340    }
1341    for (int index = 0; index < bd->attributes.size(); ++index) {
1342        QGLVertexBundleAttribute *attr = bd->attributes[index];
1343        if (d->isFixedFunction) {
1344            qt_gl_setVertexAttribute(attr->attribute, attr->value);
1345        } else {
1346            glVertexAttribPointer(GLuint(attr->attribute),
1347                                  attr->value.tupleSize(),
1348                                  attr->value.type(), GL_TRUE,
1349                                  attr->value.stride(), attr->value.data());
1350        }
1351    }
1352    d->attributeSet.unite(buffer.attributes());
1353}
1354
1355/*!
1356    Updates the projection matrix, modelview matrix, and lighting
1357    conditions in the currently active effect() object by calling
1358    QGLAbstractEffect::update().  Also updates \c{glViewport()}
1359    to cover the currentSurface() if necessary.
1360
1361    Normally this function is called automatically by draw().
1362    However, if the user wishes to use raw GL functions to draw fragments,
1363    it will be necessary to explicitly call this function to ensure that
1364    the matrix state and lighting conditions have been set on the
1365    active effect().
1366
1367    Note that this function informs the effect that an update is needed.
1368    It does not change the GL state itself, except for \c{glViewport()}.
1369    In particular, the modelview and projection matrices in the
1370    fixed-function pipeline are not changed unless the effect or
1371    application calls updateFixedFunction().
1372
1373    \sa setUserEffect(), projectionMatrix(), modelViewMatrix()
1374    \sa draw(), updateFixedFunction()
1375*/
1376void QGLPainter::update()
1377{
1378    Q_D(QGLPainter);
1379    QGLPAINTER_CHECK_PRIVATE();
1380    d->ensureEffect(this);
1381    QGLPainter::Updates updates = d->updates;
1382    d->updates = 0;
1383    if (d->modelViewMatrix.isDirty()) {
1384        updates |= UpdateModelViewMatrix;
1385        d->modelViewMatrix.setDirty(false);
1386    }
1387    if (d->projectionMatrix.isDirty()) {
1388        updates |= UpdateProjectionMatrix;
1389        d->projectionMatrix.setDirty(false);
1390    }
1391    if ((updates & UpdateViewport) != 0) {
1392        QRect viewport = currentSurface()->viewportGL();
1393        glViewport(0, 0, viewport.width(), viewport.height());
1394    }
1395    if (updates != 0)
1396        d->effect->update(this, updates);
1397}
1398
1399#if !defined(QT_OPENGL_ES_2)
1400
1401static void setLight(int light, const QGLLightParameters *parameters,
1402                     const QMatrix4x4& transform)
1403{
1404    GLfloat params[4];
1405
1406    QColor color = parameters->ambientColor();
1407    params[0] = color.redF();
1408    params[1] = color.greenF();
1409    params[2] = color.blueF();
1410    params[3] = color.alphaF();
1411    glLightfv(light, GL_AMBIENT, params);
1412
1413    color = parameters->diffuseColor();
1414    params[0] = color.redF();
1415    params[1] = color.greenF();
1416    params[2] = color.blueF();
1417    params[3] = color.alphaF();
1418    glLightfv(light, GL_DIFFUSE, params);
1419
1420    color = parameters->specularColor();
1421    params[0] = color.redF();
1422    params[1] = color.greenF();
1423    params[2] = color.blueF();
1424    params[3] = color.alphaF();
1425    glLightfv(light, GL_SPECULAR, params);
1426
1427    QVector4D vector = parameters->eyePosition(transform);
1428    params[0] = vector.x();
1429    params[1] = vector.y();
1430    params[2] = vector.z();
1431    params[3] = vector.w();
1432    glLightfv(light, GL_POSITION, params);
1433
1434    QVector3D spotDirection = parameters->eyeSpotDirection(transform);
1435    params[0] = spotDirection.x();
1436    params[1] = spotDirection.y();
1437    params[2] = spotDirection.z();
1438    glLightfv(light, GL_SPOT_DIRECTION, params);
1439
1440    params[0] = parameters->spotExponent();
1441    glLightfv(light, GL_SPOT_EXPONENT, params);
1442
1443    params[0] = parameters->spotAngle();
1444    glLightfv(light, GL_SPOT_CUTOFF, params);
1445
1446    params[0] = parameters->constantAttenuation();
1447    glLightfv(light, GL_CONSTANT_ATTENUATION, params);
1448
1449    params[0] = parameters->linearAttenuation();
1450    glLightfv(light, GL_LINEAR_ATTENUATION, params);
1451
1452    params[0] = parameters->quadraticAttenuation();
1453    glLightfv(light, GL_QUADRATIC_ATTENUATION, params);
1454}
1455
1456static void setMaterial(int face, const QGLMaterial *parameters)
1457{
1458    GLfloat params[17];
1459
1460    QColor mcolor = parameters->ambientColor();
1461    params[0] = mcolor.redF();
1462    params[1] = mcolor.greenF();
1463    params[2] = mcolor.blueF();
1464    params[3] = mcolor.alphaF();
1465
1466    mcolor = parameters->diffuseColor();
1467    params[4] = mcolor.redF();
1468    params[5] = mcolor.greenF();
1469    params[6] = mcolor.blueF();
1470    params[7] = mcolor.alphaF();
1471
1472    mcolor = parameters->specularColor();
1473    params[8] = mcolor.redF();
1474    params[9] = mcolor.greenF();
1475    params[10] = mcolor.blueF();
1476    params[11] = mcolor.alphaF();
1477
1478    mcolor = parameters->emittedLight();
1479    params[12] = mcolor.redF();
1480    params[13] = mcolor.greenF();
1481    params[14] = mcolor.blueF();
1482    params[15] = mcolor.alphaF();
1483
1484    params[16] = parameters->shininess();
1485
1486    glMaterialfv(face, GL_AMBIENT, params);
1487    glMaterialfv(face, GL_DIFFUSE, params + 4);
1488    glMaterialfv(face, GL_SPECULAR, params + 8);
1489    glMaterialfv(face, GL_EMISSION, params + 12);
1490    glMaterialfv(face, GL_SHININESS, params + 16);
1491}
1492
1493#endif // !QT_OPENGL_ES_2
1494
1495/*!
1496    Updates the fixed-function pipeline with the current painting
1497    state according to the flags in \a updates.
1498
1499    This function is intended for use by effects in their
1500    QGLAbstractEffect::update() override if they are using the
1501    fixed-function pipeline.  It can also be used by user
1502    applications if they need the QGLPainter state to be
1503    set in the fixed-function pipeline.
1504
1505    If the OpenGL implementation does not have a fixed-function
1506    pipeline, e.g. OpenGL/ES 2.0, this function does nothing.
1507
1508    \sa update()
1509*/
1510void QGLPainter::updateFixedFunction(QGLPainter::Updates updates)
1511{
1512#if defined(QT_OPENGL_ES_2)
1513    Q_UNUSED(updates);
1514#else
1515    Q_D(QGLPainter);
1516    QGLPAINTER_CHECK_PRIVATE();
1517    if ((updates & QGLPainter::UpdateColor) != 0) {
1518        QColor color;
1519        if (isPicking())
1520            color = pickColor();
1521        else
1522            color = this->color();
1523        glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());
1524    }
1525    if ((updates & QGLPainter::UpdateModelViewMatrix) != 0) {
1526        const QMatrix4x4 &matrix = d->modelViewMatrix.top();
1527        glMatrixMode(GL_MODELVIEW);
1528        if (sizeof(qreal) == sizeof(GLfloat)) {
1529            glLoadMatrixf(reinterpret_cast<const GLfloat *>
1530                (matrix.constData()));
1531        } else {
1532            GLfloat mat[16];
1533            const qreal *m = matrix.constData();
1534            for (int index = 0; index < 16; ++index)
1535                mat[index] = m[index];
1536            glLoadMatrixf(mat);
1537        }
1538    }
1539    if ((updates & QGLPainter::UpdateProjectionMatrix) != 0) {
1540        const QMatrix4x4 &matrix = d->projectionMatrix.top();
1541        glMatrixMode(GL_PROJECTION);
1542        if (sizeof(qreal) == sizeof(GLfloat)) {
1543            glLoadMatrixf(reinterpret_cast<const GLfloat *>
1544                (matrix.constData()));
1545        } else {
1546            GLfloat mat[16];
1547            const qreal *m = matrix.constData();
1548            for (int index = 0; index < 16; ++index)
1549                mat[index] = m[index];
1550            glLoadMatrixf(mat);
1551        }
1552    }
1553    if ((updates & QGLPainter::UpdateLights) != 0) {
1554        // Save the current modelview matrix and load the identity.
1555        // We need to apply the light in the modelview transformation
1556        // that was active when the light was specified.
1557        glMatrixMode(GL_MODELVIEW);
1558        glPushMatrix();
1559        glLoadIdentity();
1560
1561        // Enable the main light.
1562        const QGLLightParameters *params = mainLight();
1563        setLight(GL_LIGHT0, params, mainLightTransform());
1564
1565        // Restore the previous modelview transformation.
1566        glPopMatrix();
1567
1568        // Set up the light model parameters if at least one light is enabled.
1569        const QGLLightModel *lightModel = this->lightModel();
1570        GLfloat values[4];
1571#ifdef GL_LIGHT_MODEL_TWO_SIDE
1572        if (lightModel->model() == QGLLightModel::TwoSided)
1573            values[0] = 1.0f;
1574        else
1575            values[0] = 0.0f;
1576        glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, values);
1577#endif
1578#ifdef GL_LIGHT_MODEL_COLOR_CONTROL
1579        if (lightModel->colorControl() == QGLLightModel::SeparateSpecularColor)
1580            values[0] = GL_SEPARATE_SPECULAR_COLOR;
1581        else
1582            values[0] = GL_SINGLE_COLOR;
1583        glLightModelfv(GL_LIGHT_MODEL_COLOR_CONTROL, values);
1584#endif
1585#ifdef GL_LIGHT_MODEL_LOCAL_VIEWER
1586        if (lightModel->viewerPosition() == QGLLightModel::LocalViewer)
1587            values[0] = 1.0f;
1588        else
1589            values[0] = 0.0f;
1590        glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, values);
1591#endif
1592#ifdef GL_LIGHT_MODEL_AMBIENT
1593        QColor color = lightModel->ambientSceneColor();
1594        values[0] = color.redF();
1595        values[1] = color.blueF();
1596        values[2] = color.greenF();
1597        values[3] = color.alphaF();
1598        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, values);
1599#endif
1600    }
1601    if ((updates & QGLPainter::UpdateMaterials) != 0) {
1602        const QGLMaterial *frontMaterial = faceMaterial(QGL::FrontFaces);
1603        const QGLMaterial *backMaterial = faceMaterial(QGL::BackFaces);
1604        if (frontMaterial == backMaterial) {
1605            setMaterial(GL_FRONT_AND_BACK, frontMaterial);
1606        } else {
1607            setMaterial(GL_FRONT, frontMaterial);
1608            setMaterial(GL_BACK, backMaterial);
1609        }
1610    }
1611#endif
1612}
1613
1614/*!
1615    Draws primitives using \a count vertices from the arrays specified
1616    by setVertexAttribute().  The type of primitive to draw is specified
1617    by \a mode.
1618
1619    This operation will consume \a count values from the
1620    enabled arrays, starting at \a index.
1621
1622    \sa update()
1623*/
1624void QGLPainter::draw(QGL::DrawingMode mode, int count, int index)
1625{
1626    update();
1627    glDrawArrays((GLenum)mode, index, count);
1628}
1629
1630/*!
1631    \overload
1632
1633    Draws primitives using vertices from the arrays specified by
1634    setVertexAttribute().  The type of primitive to draw is
1635    specified by \a mode.
1636
1637    This operation will consume \a count elements of \a indices,
1638    which are used to index into the enabled arrays.
1639
1640    \sa update()
1641*/
1642void QGLPainter::draw(QGL::DrawingMode mode, const ushort *indices, int count)
1643{
1644    Q_D(QGLPainter);
1645    QGLPAINTER_CHECK_PRIVATE();
1646    update();
1647    if (d->boundIndexBuffer) {
1648        QOpenGLBuffer::release(QOpenGLBuffer::IndexBuffer);
1649        d->boundIndexBuffer = 0;
1650    }
1651    glDrawElements(GLenum(mode), count, GL_UNSIGNED_SHORT, indices);
1652}
1653
1654/*!
1655    Pushes \a surface onto the surface stack and makes it the current
1656    drawing surface for context().  If \a surface is null, then the
1657    current drawing surface will be set to the main surface (e.g. the window).
1658
1659    Note: the \a surface object must remain valid until popped from
1660    the stack or end() is called.  All surfaces are popped from
1661    the stack by end().
1662
1663    The UpdateViewport flag will be set to indicate that the
1664    \c{glViewport()} should be adjusted to the extents of \a surface
1665    when update() is next called.
1666
1667    \sa popSurface(), currentSurface(), setSurface()
1668    \sa QGLAbstractSurface::activate()
1669*/
1670void QGLPainter::pushSurface(QGLAbstractSurface *surface)
1671{
1672    Q_D(QGLPainter);
1673    QGLPAINTER_CHECK_PRIVATE();
1674    Q_ASSERT(surface);
1675    if (!surface) {
1676        // Find the most recent main surface for this painter.
1677        int size = d->surfaceStack.size();
1678        while (size > 0 && !d->surfaceStack[size - 1].mainSurface)
1679            --size;
1680        if (!size)
1681            return;     // Shouldn't happen, but be safe anyway.
1682        surface = d->surfaceStack[size - 1].surface;
1683    }
1684    Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1685    QGLAbstractSurface *current = d->surfaceStack.top().surface;
1686    QGLPainterSurfaceInfo psurf;
1687    psurf.surface = surface;
1688    psurf.destroySurface = false;
1689    psurf.mainSurface = false;
1690    d->surfaceStack.append(psurf);
1691    current->switchTo(surface);
1692    d->updates |= UpdateViewport;
1693}
1694
1695/*!
1696    Pops the top-most drawing surface from the surface stack
1697    and returns it.  The next object on the stack will be made
1698    the current drawing surface for context().  Returns null if the
1699    surface stack is already at the main surface (e.g. the window).
1700
1701    The UpdateViewport flag will be set to indicate that the
1702    \c{glViewport()} should be adjusted to the new surface extents
1703    when update() is next called.
1704
1705    \sa pushSurface(), currentSurface(), setSurface()
1706*/
1707QGLAbstractSurface *QGLPainter::popSurface()
1708{
1709    Q_D(QGLPainter);
1710    QGLPAINTER_CHECK_PRIVATE();
1711    Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1712    QGLPainterSurfaceInfo &surf = d->surfaceStack.top();
1713    if (surf.mainSurface)
1714        return 0;
1715    QGLAbstractSurface *surface = surf.surface;
1716    d->surfaceStack.pop();
1717    Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1718    QGLAbstractSurface *nextSurface = d->surfaceStack.top().surface;
1719    surface->switchTo(nextSurface);
1720    d->updates |= UpdateViewport;
1721    return surface;
1722}
1723
1724/*!
1725    Sets the top-most drawing surface on the surface stack to \a surface
1726    and activate it.
1727
1728    Note: if the top-most drawing surface is the main surface specified
1729    during begin(), then this function will perform a pushSurface()
1730    instead.  Typically this function is used to replace the last
1731    surface that was pushed onto the stack and avoid doing popSurface()
1732    followed by pushSurface().  The main surface cannot be replaced
1733    in this manner.
1734
1735    The UpdateViewport flag will be set to indicate that the
1736    \c{glViewport()} should be adjusted to the extents of \a surface
1737    when update() is next called.
1738
1739    \sa pushSurface(), popSurface(), currentSurface()
1740*/
1741void QGLPainter::setSurface(QGLAbstractSurface *surface)
1742{
1743    Q_D(QGLPainter);
1744    QGLPAINTER_CHECK_PRIVATE();
1745    Q_ASSERT(surface);
1746    Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1747    QGLPainterSurfaceInfo &surf = d->surfaceStack.top();
1748    if (surf.mainSurface) {
1749        pushSurface(surface);
1750        return;
1751    }
1752    QGLAbstractSurface *oldSurface = surf.surface;
1753    surf.surface = surface;
1754    oldSurface->switchTo(surface);
1755    d->updates |= UpdateViewport;
1756}
1757
1758/*!
1759    Returns the current drawing surface.
1760
1761    \sa pushSurface(), popSurface(), setSurface()
1762*/
1763QGLAbstractSurface *QGLPainter::currentSurface() const
1764{
1765    Q_D(const QGLPainter);
1766    QGLPAINTER_CHECK_PRIVATE();
1767    Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1768    return d->surfaceStack.top().surface;
1769}
1770
1771/*!
1772    Returns the current lighting model.
1773
1774    \sa setLightModel()
1775*/
1776const QGLLightModel *QGLPainter::lightModel() const
1777{
1778    Q_D(QGLPainter);
1779    QGLPAINTER_CHECK_PRIVATE();
1780    if (!d->lightModel) {
1781        if (!d->defaultLightModel)
1782            d->defaultLightModel = new QGLLightModel();
1783        d->lightModel = d->defaultLightModel;
1784    }
1785    return d->lightModel;
1786}
1787
1788/*!
1789    Sets the current lighting model to \a value.  If \a value is
1790    null, then the default lighting model parameters will be used.
1791
1792    The light settings in the GL server will not be changed until
1793    update() is called.
1794
1795    \sa lightModel()
1796*/
1797void QGLPainter::setLightModel(const QGLLightModel *value)
1798{
1799    Q_D(QGLPainter);
1800    QGLPAINTER_CHECK_PRIVATE();
1801    d->lightModel = value;
1802    d->updates |= QGLPainter::UpdateLights;
1803}
1804
1805/*!
1806    Returns the parameters for the main light in the scene.
1807
1808    The light parameters are specified in world co-ordinates at
1809    the point when setMainLight() was called.  The mainLightTransform()
1810    must be applied to obtain eye co-ordinates.
1811
1812    This function is a convenience that returns the light with
1813    identifier 0.  If light 0 is not currently enabled, then a
1814    default light is added to the painter with an identity
1815    transform and then returned as the main light.
1816
1817    \sa setMainLight(), mainLightTransform(), addLight()
1818*/
1819const QGLLightParameters *QGLPainter::mainLight() const
1820{
1821    Q_D(QGLPainter);
1822    QGLPAINTER_CHECK_PRIVATE();
1823    if (d->lights.isEmpty()) {
1824        if (!d->defaultLight)
1825            d->defaultLight = new QGLLightParameters();
1826        d->lights.append(d->defaultLight);
1827        d->lightTransforms.append(QMatrix4x4());
1828    } else if (!d->lights[0]) {
1829        if (!d->defaultLight)
1830            d->defaultLight = new QGLLightParameters();
1831        d->lights[0] = d->defaultLight;
1832        d->lightTransforms[0] = QMatrix4x4();
1833    }
1834    return d->lights[0];
1835}
1836
1837/*!
1838    Sets the \a parameters for the main light in the scene.
1839    The mainLightTransform() is set to the current modelViewMatrix().
1840
1841    Light parameters are stored in world co-ordinates, not eye co-ordinates.
1842    The mainLightTransform() specifies the transformation to apply to
1843    convert the world co-ordinates into eye co-ordinates when the light
1844    is used.
1845
1846    Note: the \a parameters may be ignored by effect() if it
1847    has some other way to determine the lighting conditions.
1848
1849    The light settings in the GL server will not be changed until
1850    update() is called.
1851
1852    This function is a convenience that sets the light with
1853    identifier 0.  If \a parameters is null, then light 0
1854    will be removed.
1855
1856    \sa mainLight(), mainLightTransform(), addLight()
1857*/
1858void QGLPainter::setMainLight(const QGLLightParameters *parameters)
1859{
1860    Q_D(QGLPainter);
1861    QGLPAINTER_CHECK_PRIVATE();
1862    if (d->lights.isEmpty()) {
1863        if (parameters) {
1864            d->lights.append(parameters);
1865            d->lightTransforms.append(modelViewMatrix());
1866            d->updates |= QGLPainter::UpdateLights;
1867        }
1868    } else if (parameters) {
1869        d->lights[0] = parameters;
1870        d->lightTransforms[0] = modelViewMatrix();
1871        d->updates |= QGLPainter::UpdateLights;
1872    } else {
1873        removeLight(0);
1874    }
1875}
1876
1877/*!
1878    Sets the \a parameters for the main light in the scene, and set
1879    mainLightTransform() to \a transform.
1880
1881    Light parameters are stored in world co-ordinates, not eye co-ordinates.
1882    The \a transform specifies the transformation to apply to convert the
1883    world co-ordinates into eye co-ordinates when the light is used.
1884
1885    Note: the \a parameters may be ignored by effect() if it
1886    has some other way to determine the lighting conditions.
1887
1888    The light settings in the GL server will not be changed until
1889    update() is called.
1890
1891    This function is a convenience that sets the light with
1892    identifier 0.  If \a parameters is null, then light 0
1893    will be removed.
1894
1895    \sa mainLight(), mainLightTransform()
1896*/
1897void QGLPainter::setMainLight
1898        (const QGLLightParameters *parameters, const QMatrix4x4& transform)
1899{
1900    Q_D(QGLPainter);
1901    QGLPAINTER_CHECK_PRIVATE();
1902    if (d->lights.isEmpty()) {
1903        if (parameters) {
1904            d->lights.append(parameters);
1905            d->lightTransforms.append(transform);
1906            d->updates |= QGLPainter::UpdateLights;
1907        }
1908    } else if (parameters) {
1909        d->lights[0] = parameters;
1910        d->lightTransforms[0] = transform;
1911        d->updates |= QGLPainter::UpdateLights;
1912    } else {
1913        removeLight(0);
1914    }
1915}
1916
1917/*!
1918    Returns the modelview transformation matrix for the main light that
1919    was set at the time setMainLight() was called.
1920
1921    The light transform may be used by later painting operations to
1922    convert the light from world co-ordinates into eye co-ordinates.
1923    The eye transformation is set when the light is specified.
1924
1925    This function is a convenience that returns the tranform for the
1926    light with identifier 0.  If light 0 is not enabled, then the
1927    function returns the identity matrix.
1928
1929    \sa mainLight(), setMainLight(), addLight()
1930*/
1931QMatrix4x4 QGLPainter::mainLightTransform() const
1932{
1933    Q_D(const QGLPainter);
1934    QGLPAINTER_CHECK_PRIVATE();
1935    if (!d->lights.isEmpty() && d->lights[0])
1936        return d->lightTransforms[0];
1937    else
1938        return QMatrix4x4();
1939}
1940
1941/*!
1942    Adds a light to this painter, with the specified \a parameters.
1943    The lightTransform() for the light is set to the current
1944    modelViewMatrix().  Returns an identifier for the light.
1945
1946    Light parameters are stored in world co-ordinates, not eye co-ordinates.
1947    The lightTransform() specifies the transformation to apply to
1948    convert the world co-ordinates into eye co-ordinates when the light
1949    is used.
1950
1951    Note: the \a parameters may be ignored by effect() if it
1952    has some other way to determine the lighting conditions.
1953
1954    The light settings in the GL server will not be changed until
1955    update() is called.
1956
1957    \sa removeLight(), light(), mainLight()
1958*/
1959int QGLPainter::addLight(const QGLLightParameters *parameters)
1960{
1961    return addLight(parameters, modelViewMatrix());
1962}
1963
1964/*!
1965    Adds a light to this painter, with the specified \a parameters.
1966    The lightTransform() for the light is set to \a transform.
1967    Returns an identifier for the light.
1968
1969    Light parameters are stored in world co-ordinates, not eye co-ordinates.
1970    The \a transform specifies the transformation to apply to
1971    convert the world co-ordinates into eye co-ordinates when the light
1972    is used.
1973
1974    Note: the \a parameters may be ignored by effect() if it
1975    has some other way to determine the lighting conditions.
1976
1977    The light settings in the GL server will not be changed until
1978    update() is called.
1979
1980    \sa removeLight(), light(), mainLight()
1981*/
1982int QGLPainter::addLight(const QGLLightParameters *parameters, const QMatrix4x4 &transform)
1983{
1984    Q_ASSERT(parameters);
1985    Q_D(QGLPainter);
1986    QGLPAINTER_CHECK_PRIVATE();
1987    int lightId = 0;
1988    while (lightId < d->lights.size() && d->lights[lightId] != 0)
1989        ++lightId;
1990    if (lightId < d->lights.size()) {
1991        d->lights[lightId] = parameters;
1992        d->lightTransforms[lightId] = transform;
1993    } else {
1994        d->lights.append(parameters);
1995        d->lightTransforms.append(transform);
1996    }
1997    d->updates |= QGLPainter::UpdateLights;
1998    return lightId;
1999}
2000
2001/*!
2002    Removes the light with the specified \a lightId.
2003
2004    \sa addLight(), light()
2005*/
2006void QGLPainter::removeLight(int lightId)
2007{
2008    Q_D(QGLPainter);
2009    QGLPAINTER_CHECK_PRIVATE();
2010    if (lightId >= 0 && lightId < d->lights.size()) {
2011        d->lights[lightId] = 0;
2012        if (lightId >= (d->lights.size() - 1)) {
2013            do {
2014                d->lights.resize(lightId);
2015                d->lightTransforms.resize(lightId);
2016                --lightId;
2017            } while (lightId >= 0 && d->lights[lightId] == 0);
2018        }
2019        d->updates |= QGLPainter::UpdateLights;
2020    }
2021}
2022
2023/*!
2024    Returns the maximum light identifier currently in use on this painter;
2025    or -1 if there are no lights.
2026
2027    It is possible that some light identifiers less than maximumLightId()
2028    may be invalid because the lights have been removed.  Use the following
2029    code to locate all enabled lights:
2030
2031    \code
2032    int maxLightId = painter.maximumLightId();
2033    for (int lightId = 0; index <= maxLightId; ++index) {
2034        const QGLLightParameters *params = painter.light(lightId);
2035        if (params) {
2036            ...
2037        }
2038    }
2039    \endcode
2040
2041    \sa addLight(), light()
2042*/
2043int QGLPainter::maximumLightId() const
2044{
2045    Q_D(const QGLPainter);
2046    QGLPAINTER_CHECK_PRIVATE();
2047    return d->lights.size() - 1;
2048}
2049
2050/*!
2051    Returns the parameters for the light with the identifier \a lightId;
2052    or null if \a lightId is not valid or has been removed.
2053
2054    \sa addLight(), removeLight(), lightTransform()
2055*/
2056const QGLLightParameters *QGLPainter::light(int lightId) const
2057{
2058    Q_D(const QGLPainter);
2059    QGLPAINTER_CHECK_PRIVATE();
2060    if (lightId >= 0 && lightId < d->lights.size())
2061        return d->lights[lightId];
2062    else
2063        return 0;
2064}
2065
2066/*!
2067    Returns the modelview transformation for the light with the identifier
2068    \a lightId; or the identity matrix if \a lightId is not valid or has
2069    been removed.
2070
2071    \sa addLight(), removeLight(), light()
2072*/
2073QMatrix4x4 QGLPainter::lightTransform(int lightId) const
2074{
2075    Q_D(const QGLPainter);
2076    QGLPAINTER_CHECK_PRIVATE();
2077    if (lightId >= 0 && lightId < d->lights.size() && d->lights[lightId])
2078        return d->lightTransforms[lightId];
2079    else
2080        return QMatrix4x4();
2081}
2082
2083/*!
2084    Returns the material that is used for drawing \a face on polygons.
2085    If \a face is QGL::FrontFaces or QGL::AllFaces, then the front
2086    material is returned.  If \a face is QGL::BackFaces, then the
2087    back material is returned.
2088
2089    \sa setFaceMaterial(), setFaceColor()
2090*/
2091const QGLMaterial *QGLPainter::faceMaterial(QGL::Face face) const
2092{
2093    Q_D(QGLPainter);
2094    QGLPAINTER_CHECK_PRIVATE();
2095    if (face == QGL::BackFaces) {
2096        if (!d->backMaterial) {
2097            if (!d->defaultMaterial)
2098                d->defaultMaterial = new QGLMaterial();
2099            d->backMaterial = d->defaultMaterial;
2100        }
2101        return d->backMaterial;
2102    } else {
2103        if (!d->frontMaterial) {
2104            if (!d->defaultMaterial)
2105                d->defaultMaterial = new QGLMaterial();
2106            d->frontMaterial = d->defaultMaterial;
2107        }
2108        return d->frontMaterial;
2109    }
2110}
2111
2112/*!
2113    Sets the material that is used for drawing \a face on polygons
2114    to \a value.  If \a face is QGL::FrontFaces, then the front
2115    material is set.  If \a face is QGL::BackFaces, then the
2116    back material is set.  If \a face is QGL::AllFaces, then both
2117    the front and back materials are set.
2118
2119    If \a value is null, then the \a face material will be set to
2120    the default material properties.
2121
2122    The material settings in the GL server will not be changed until
2123    update() is called.
2124
2125    \sa faceMaterial(), setFaceColor()
2126*/
2127void QGLPainter::setFaceMaterial
2128        (QGL::Face face, const QGLMaterial *value)
2129{
2130    Q_D(QGLPainter);
2131    QGLPAINTER_CHECK_PRIVATE();
2132    if (face == QGL::FrontFaces) {
2133        if (d->frontMaterial == value)
2134            return;
2135        d->frontMaterial = value;
2136    } else if (face == QGL::BackFaces) {
2137        if (d->backMaterial == value)
2138            return;
2139        d->backMaterial = value;
2140    } else {
2141        if (d->frontMaterial == value && d->backMaterial == value)
2142            return;
2143        d->frontMaterial = value;
2144        d->backMaterial = value;
2145    }
2146    d->updates |= QGLPainter::UpdateMaterials;
2147}
2148
2149static QGLMaterial *createColorMaterial
2150    (QGLMaterial *prev, const QColor& color)
2151{
2152    QGLMaterial *material;
2153    if (prev)
2154        material = prev;
2155    else
2156        material = new QGLMaterial();
2157    material->setColor(color);
2158    return material;
2159}
2160
2161/*!
2162    Sets the material that is used for drawing \a face on polygons
2163    to \a color.  This is a convenience function for setting materials
2164    to simple colors.
2165
2166    The RGB components of the ambient color of the material will be set
2167    to 20% of \a color, and the RGB components of the diffuse color of the
2168    material will be set to 80% of \a color.  The alpha components of
2169    the ambient and diffuse material colors will both be set to the
2170    alpha component of \a color.
2171
2172    If \a face is QGL::FrontFaces, then the front material is set.
2173    If \a face is QGL::BackFaces, then the back material is set.
2174    If \a face is QGL::AllFaces, then both the front and back
2175    materials are set.
2176
2177    The material settings in the GL server will not be changed until
2178    update() is called.
2179
2180    \sa faceMaterial(), setFaceMaterial()
2181*/
2182void QGLPainter::setFaceColor(QGL::Face face, const QColor& color)
2183{
2184    Q_D(QGLPainter);
2185    QGLPAINTER_CHECK_PRIVATE();
2186    if (face == QGL::FrontFaces) {
2187        d->frontColorMaterial =
2188            createColorMaterial(d->frontColorMaterial, color);
2189        d->frontMaterial = d->frontColorMaterial;
2190    } else if (face == QGL::BackFaces) {
2191        d->backColorMaterial =
2192            createColorMaterial(d->backColorMaterial, color);
2193        d->backMaterial = d->backColorMaterial;
2194    } else {
2195        d->frontColorMaterial =
2196            createColorMaterial(d->frontColorMaterial, color);
2197        d->backColorMaterial =
2198            createColorMaterial(d->backColorMaterial, color);
2199        d->frontMaterial = d->frontColorMaterial;
2200        d->backMaterial = d->backColorMaterial;
2201    }
2202    d->updates |= QGLPainter::UpdateMaterials;
2203}
2204
2205/*!
2206    Returns true if this painter is in object picking mode;
2207    false if this painter is in normal rendering mode.
2208
2209    \sa setPicking(), objectPickId()
2210*/
2211bool QGLPainter::isPicking() const
2212{
2213    Q_D(QGLPainter);
2214    QGLPAINTER_CHECK_PRIVATE();
2215    return (d->pick ? d->pick->isPicking : false);
2216}
2217
2218/*!
2219    Enables or disables object picking mode according to \a value.
2220
2221    If \a value is true, then the effect() will be overridden with a
2222    simple flat color effect that renders objects with pickColor().
2223    These colors can be read back later with pickObject().
2224
2225    \sa isPicking(), objectPickId(), pickObject()
2226*/
2227void QGLPainter::setPicking(bool value)
2228{
2229    Q_D(QGLPainter);
2230    QGLPAINTER_CHECK_PRIVATE();
2231    if (!d->pick)
2232        d->pick = new QGLPainterPickPrivate();
2233    if (d->pick->isPicking != value) {
2234        // Switch to/from the pick effect.
2235        d->pick->isPicking = value;
2236        if (d->effect)
2237            d->effect->setActive(this, false);
2238        d->effect = 0;
2239        d->ensureEffect(this);
2240    }
2241}
2242
2243/*!
2244    Returns the current object pick identifier.  The default value
2245    is -1 which indicates that rendered objects should not have a
2246    pickColor() associated with them.
2247
2248    \sa setObjectPickId(), clearPickObjects(), pickObject()
2249*/
2250int QGLPainter::objectPickId() const
2251{
2252    Q_D(QGLPainter);
2253    QGLPAINTER_CHECK_PRIVATE();
2254    return (d->pick ? d->pick->objectPickId : -1);
2255}
2256
2257/*!
2258    Sets the current object pick identifier to \a value.  If \a value
2259    is -1, then subsequent objects will be rendered without a pickColor().
2260
2261    If value is not -1, then the pickColor() is changed to a color
2262    that represents that object pick identifier.  If \a value has been
2263    seen previously, then the same pickColor() as last time will
2264    be returned.
2265
2266    The function call will be ignored if isPicking() is false.
2267
2268    \sa objectPickId(), clearPickObjects(), pickObject()
2269*/
2270void QGLPainter::setObjectPickId(int value)
2271{
2272    Q_D(QGLPainter);
2273    QGLPAINTER_CHECK_PRIVATE();
2274    if (!d->pick || !d->pick->isPicking)
2275        return;
2276    d->pick->objectPickId = value;
2277    if (value != -1) {
2278        QRgb color = d->pick->pickObjectToColor.value(value, 0);
2279        if (!color) {
2280            color = qt_qgl_pick_color(d->pick->pickColorIndex++);
2281            d->pick->pickObjectToColor[value] = color;
2282            d->pick->pickColorToObject[color] = value;
2283        }
2284        d->pick->pickColor = color;
2285        d->updates |= UpdateColor;
2286    } else {
2287        d->pick->pickColor = 0;
2288        d->updates |= UpdateColor;
2289    }
2290}
2291
2292/*!
2293    Clears the objectPickId() to pickColor() mappings that
2294    were used previously.  This will also set objectPickId()
2295    to -1 and pickColor() to (0, 0, 0, 1).
2296
2297    The function call will be ignored if isPicking() is false.
2298
2299    \sa objectPickId(), pickColor()
2300*/
2301void QGLPainter::clearPickObjects()
2302{
2303    Q_D(QGLPainter);
2304    QGLPAINTER_CHECK_PRIVATE();
2305    if (d->pick && d->pick->isPicking) {
2306        d->pick->pickObjectToColor.clear();
2307        d->pick->pickColorToObject.clear();
2308        d->pick->pickColorIndex = 0;
2309        d->pick->objectPickId = -1;
2310        d->pick->pickColor = 0;
2311        d->updates |= UpdateColor;
2312    }
2313}
2314
2315/*!
2316    Returns the current pick color to use to render the object
2317    associated with objectPickId().  The returned color will
2318    be (0, 0, 0, 1) if objectPickId() is -1.
2319
2320    \sa objectPickId(), clearPickObjects()
2321*/
2322QColor QGLPainter::pickColor() const
2323{
2324    Q_D(QGLPainter);
2325    QGLPAINTER_CHECK_PRIVATE();
2326    if (d->pick) {
2327        QColor color;
2328        color.setRgb(d->pick->pickColor);
2329        return color;
2330    } else {
2331        return Qt::black;
2332    }
2333}
2334
2335/*!
2336    Picks the color at (\a x, \a y) in the color buffer and
2337    returns the objectPickId() that corresponds to that color.
2338    Returns -1 if (\a x, \a y) is not positioned over a
2339    recognized object.  The origin (0, 0) is assumed to be
2340    the bottom-left corner of the drawing surface.
2341
2342    \sa objectPickId()
2343*/
2344int QGLPainter::pickObject(int x, int y) const
2345{
2346    Q_D(QGLPainter);
2347    QGLPAINTER_CHECK_PRIVATE();
2348
2349    if (!d->pick)
2350    {
2351        return -1;
2352    }
2353
2354    // Fetch the color at the specified pixel.
2355    unsigned char data[4] = {0, 0, 0, 0};
2356    glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
2357    QRgb color = qRgb(data[0], data[1], data[2]);
2358
2359    // Normalize the color to account for floating-point rounding.
2360    color = qt_qgl_normalize_pick_color(color); // XXX: detect RGB444 screens.
2361
2362    // Map the color back to an object identifier.
2363    return d->pick->pickColorToObject.value(color, -1);
2364}
2365
2366QT_END_NAMESPACE