~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/opengl/qgl_p.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/****************************************************************************
2
2
**
3
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
4
5
** Contact: Nokia Corporation (qt-info@nokia.com)
5
6
**
6
7
** This file is part of the QtOpenGL module of the Qt Toolkit.
7
8
**
8
9
** $QT_BEGIN_LICENSE:LGPL$
9
 
** Commercial Usage
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Commercial License Agreement provided with the
12
 
** Software or, alternatively, in accordance with the terms contained in
13
 
** a written agreement between you and Nokia.
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
14
15
**
15
16
** GNU Lesser General Public License Usage
16
17
** Alternatively, this file may be used under the terms of the GNU Lesser
20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
23
**
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
27
 
**
28
 
** GNU General Public License Usage
29
 
** Alternatively, this file may be used under the terms of the GNU
30
 
** General Public License version 3.0 as published by the Free Software
31
 
** Foundation and appearing in the file LICENSE.GPL included in the
32
 
** packaging of this file.  Please review the following information to
33
 
** ensure the GNU General Public License version 3.0 requirements will be
34
 
** met: http://www.gnu.org/copyleft/gpl.html.
35
 
**
36
 
** If you are unsure which license is appropriate for your use, please
37
 
** contact the sales department at http://www.qtsoftware.com/contact.
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
38
38
** $QT_END_LICENSE$
39
39
**
40
40
****************************************************************************/
59
59
#include "QtCore/qthread.h"
60
60
#include "QtCore/qthreadstorage.h"
61
61
#include "QtCore/qhash.h"
 
62
#include "QtCore/qatomic.h"
62
63
#include "private/qwidget_p.h"
 
64
#include "qcache.h"
 
65
#include "qglpaintdevice_p.h"
63
66
 
64
67
#ifndef QT_OPENGL_ES_1_CL
65
68
#define q_vertexType float
126
129
class QGLFormatPrivate
127
130
{
128
131
public:
129
 
    QGLFormatPrivate() {
 
132
    QGLFormatPrivate()
 
133
        : ref(1)
 
134
    {
130
135
        opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer;
131
136
#if defined(QT_OPENGL_ES_2)
132
137
        opts |= QGL::SampleBuffers;
136
141
        numSamples = -1;
137
142
        swapInterval = -1;
138
143
    }
 
144
    QGLFormatPrivate(const QGLFormatPrivate *other)
 
145
        : ref(1),
 
146
          opts(other->opts),
 
147
          pln(other->pln),
 
148
          depthSize(other->depthSize),
 
149
          accumSize(other->accumSize),
 
150
          stencilSize(other->stencilSize),
 
151
          redSize(other->redSize),
 
152
          greenSize(other->greenSize),
 
153
          blueSize(other->blueSize),
 
154
          alphaSize(other->alphaSize),
 
155
          numSamples(other->numSamples),
 
156
          swapInterval(other->swapInterval)
 
157
    {
 
158
    }
 
159
    QAtomicInt ref;
139
160
    QGL::FormatOptions opts;
140
161
    int pln;
141
162
    int depthSize;
154
175
    Q_DECLARE_PUBLIC(QGLWidget)
155
176
public:
156
177
    QGLWidgetPrivate() : QWidgetPrivate()
 
178
                       , disable_clear_on_painter_begin(false)
157
179
#ifdef Q_WS_QWS
158
180
                       , wsurf(0)
159
181
#endif
170
192
    void cleanupColormaps();
171
193
 
172
194
    QGLContext *glcx;
 
195
    QGLWidgetGLPaintDevice glDevice;
173
196
    bool autoSwap;
174
197
 
175
198
    QGLColormap cmap;
 
199
#ifndef QT_OPENGL_ES
176
200
    QMap<QString, int> displayListCache;
 
201
#endif
 
202
 
 
203
    bool disable_clear_on_painter_begin;
177
204
 
178
205
#if defined(Q_WS_WIN)
179
206
    void updateColormap();
192
219
#endif
193
220
};
194
221
 
 
222
class QGLContextResource;
 
223
class QGLSharedResourceGuard;
 
224
 
 
225
// QGLContextPrivate has the responsibility of creating context groups.
 
226
// QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy
 
227
// context groups when needed.
 
228
// QGLShareRegister has the responsibility of keeping the context pointer up to date.
 
229
class QGLContextGroup
 
230
{
 
231
public:
 
232
    ~QGLContextGroup();
 
233
 
 
234
    QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
 
235
    const QGLContext *context() const {return m_context;}
 
236
 
 
237
    void addGuard(QGLSharedResourceGuard *guard);
 
238
    void removeGuard(QGLSharedResourceGuard *guard);
 
239
private:
 
240
    QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
 
241
 
 
242
    QGLExtensionFuncs m_extensionFuncs;
 
243
    const QGLContext *m_context; // context group's representative
 
244
    QList<const QGLContext *> m_shares;
 
245
    QHash<QGLContextResource *, void *> m_resources;
 
246
    QGLSharedResourceGuard *m_guards; // double-linked list of active guards.
 
247
    QAtomicInt m_refs;
 
248
 
 
249
    void cleanupResources(const QGLContext *ctx);
 
250
 
 
251
    friend class QGLShareRegister;
 
252
    friend class QGLContext;
 
253
    friend class QGLContextPrivate;
 
254
    friend class QGLContextResource;
 
255
};
 
256
 
 
257
class QGLTexture;
 
258
 
195
259
class QGLContextPrivate
196
260
{
197
261
    Q_DECLARE_PUBLIC(QGLContext)
198
262
public:
199
 
    explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {}
200
 
    ~QGLContextPrivate() {}
201
 
    GLuint bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
202
 
                       bool clean = false);
203
 
    GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean);
204
 
    GLuint bindTexture(const QImage &image, GLenum target, GLint format, bool clean);
205
 
    bool textureCacheLookup(const qint64 key, GLenum target, GLuint *id);
 
263
    explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
 
264
    ~QGLContextPrivate();
 
265
    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
 
266
                            QGLContext::BindOptions options);
 
267
    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
 
268
                            QGLContext::BindOptions options);
 
269
    QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
 
270
                            QGLContext::BindOptions options);
 
271
    QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
206
272
    void init(QPaintDevice *dev, const QGLFormat &format);
207
273
    QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
208
274
    int maxTextureSize();
220
286
#endif
221
287
#if defined(QT_OPENGL_ES)
222
288
    QEglContext *eglContext;
 
289
    EGLSurface eglSurface;
223
290
#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
224
291
    void* cx;
225
292
#endif
230
297
    void* pbuf;
231
298
    quint32 gpm;
232
299
    int screen;
 
300
    QHash<QPixmapData*, QPixmap> boundPixmaps;
 
301
    QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
 
302
                                            QGLContext::BindOptions options);
 
303
    static void destroyGlSurfaceForPixmap(QPixmapData*);
 
304
    static void unbindPixmapFromTexture(QPixmapData*);
233
305
#endif
234
306
#if defined(Q_WS_MAC)
235
307
    bool update;
238
310
#endif
239
311
    QGLFormat glFormat;
240
312
    QGLFormat reqFormat;
241
 
    GLuint pbo;
 
313
    GLuint fbo;
242
314
 
243
315
    uint valid : 1;
244
316
    uint sharing : 1;
245
317
    uint initDone : 1;
246
318
    uint crWin : 1;
247
 
    uint clear_on_painter_begin : 1;
248
319
    uint internal_context : 1;
249
320
    uint version_flags_cached : 1;
250
321
    QPaintDevice *paintDevice;
252
323
    QGLContext *q_ptr;
253
324
    QGLFormat::OpenGLVersionFlags version_flags;
254
325
 
255
 
    QGLExtensionFuncs extensionFuncs;
 
326
    QGLContextGroup *group;
256
327
    GLint max_texture_size;
257
328
 
 
329
    GLuint current_fbo;
 
330
    QPaintEngine *active_engine;
 
331
 
 
332
    static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
 
333
 
258
334
#ifdef Q_WS_WIN
259
 
    static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; }
 
335
    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
260
336
#endif
261
337
 
262
338
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
263
339
    static QGLExtensionFuncs qt_extensionFuncs;
264
 
    static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *) { return qt_extensionFuncs; }
 
340
    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
265
341
#endif
266
342
 
267
 
    QPixmapFilter *createPixmapFilter(int type) const;
 
343
    static void setCurrentContext(QGLContext *context);
268
344
};
269
345
 
270
346
// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
271
 
class QGLSignalProxy : public QObject
 
347
class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
272
348
{
273
349
    Q_OBJECT
274
350
public:
296
372
        StencilWrap             = 0x00000100,
297
373
        PackedDepthStencil      = 0x00000200,
298
374
        NVFloatBuffer           = 0x00000400,
299
 
        PixelBufferObject       = 0x00000800
 
375
        PixelBufferObject       = 0x00000800,
 
376
        FramebufferBlit         = 0x00001000,
 
377
        NPOTTextures            = 0x00002000
300
378
    };
301
379
    Q_DECLARE_FLAGS(Extensions, Extension)
302
380
 
309
387
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
310
388
 
311
389
 
312
 
struct QGLThreadContext {
313
 
    QGLContext *context;
314
 
};
315
 
extern QThreadStorage<QGLThreadContext *> qgl_context_storage;
316
 
 
317
 
typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash;
318
 
class QGLShareRegister
 
390
class Q_AUTOTEST_EXPORT QGLShareRegister
319
391
{
320
392
public:
321
393
    QGLShareRegister() {}
322
 
    ~QGLShareRegister() { reg.clear(); }
323
 
 
324
 
    bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) {
325
 
        if (context1 == context2)
326
 
            return true;
327
 
        QList<const QGLContext *> shares = reg.values(context1);
328
 
        for (int k=0; k<shares.size(); ++k) {
329
 
            const QGLContext *ctx = shares.at(k);
330
 
            if (ctx == skip) // avoid an indirect circular loop (infinite recursion)
331
 
                continue;
332
 
            if (ctx == context2)
333
 
                return true;
334
 
            if (checkSharing(ctx, context2, context1))
335
 
                return true;
336
 
        }
337
 
        return false;
338
 
    }
339
 
 
340
 
    void addShare(const QGLContext *context, const QGLContext *share) {
341
 
        reg.insert(context, share); // context sharing works both ways
342
 
        reg.insert(share, context);
343
 
    }
344
 
 
345
 
    void removeShare(const QGLContext *context) {
346
 
        QGLSharingHash::iterator it = reg.begin();
347
 
        while (it != reg.end()) {
348
 
            if (it.key() == context || it.value() == context)
349
 
                it = reg.erase(it);
350
 
            else
351
 
                ++it;
352
 
        }
353
 
    }
354
 
 
355
 
    void replaceShare(const QGLContext *oldContext, const QGLContext *newContext) {
356
 
        QGLSharingHash::iterator it = reg.begin();
357
 
        while (it != reg.end()) {
358
 
            if (it.key() == oldContext)
359
 
                reg.insert(newContext, it.value());
360
 
            else if (it.value() == oldContext)
361
 
                reg.insert(it.key(), newContext);
362
 
            ++it;
363
 
        }
364
 
        removeShare(oldContext);
365
 
    }
366
 
 
367
 
private:
368
 
    QGLSharingHash reg;
 
394
    ~QGLShareRegister() {}
 
395
 
 
396
    void addShare(const QGLContext *context, const QGLContext *share);
 
397
    QList<const QGLContext *> shares(const QGLContext *context);
 
398
    void removeShare(const QGLContext *context);
369
399
};
370
400
 
371
401
extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
372
402
 
 
403
// Temporarily make a context current if not already current or
 
404
// shared with the current contex.  The previous context is made
 
405
// current when the object goes out of scope.
 
406
class Q_OPENGL_EXPORT QGLShareContextScope
 
407
{
 
408
public:
 
409
    QGLShareContextScope(const QGLContext *ctx)
 
410
        : m_oldContext(0)
 
411
    {
 
412
        QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
 
413
        if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
 
414
            m_oldContext = currentContext;
 
415
            m_ctx = const_cast<QGLContext *>(ctx);
 
416
            m_ctx->makeCurrent();
 
417
        } else {
 
418
            m_ctx = currentContext;
 
419
        }
 
420
    }
 
421
 
 
422
    operator QGLContext *()
 
423
    {
 
424
        return m_ctx;
 
425
    }
 
426
 
 
427
    QGLContext *operator->()
 
428
    {
 
429
        return m_ctx;
 
430
    }
 
431
 
 
432
    ~QGLShareContextScope()
 
433
    {
 
434
        if (m_oldContext)
 
435
            m_oldContext->makeCurrent();
 
436
    }
 
437
 
 
438
private:
 
439
    QGLContext *m_oldContext;
 
440
    QGLContext *m_ctx;
 
441
};
 
442
 
 
443
class QGLTexture {
 
444
public:
 
445
    QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
 
446
               QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
 
447
        : context(ctx),
 
448
          id(tx_id),
 
449
          target(tx_target),
 
450
          options(opt)
 
451
#if defined(Q_WS_X11)
 
452
        , boundPixmap(0)
 
453
#endif
 
454
    {}
 
455
 
 
456
    ~QGLTexture() {
 
457
        if (options & QGLContext::MemoryManagedBindOption) {
 
458
            Q_ASSERT(context);
 
459
            QGLShareContextScope scope(context);
 
460
#if defined(Q_WS_X11)
 
461
            // Although glXReleaseTexImage is a glX call, it must be called while there
 
462
            // is a current context - the context the pixmap was bound to a texture in.
 
463
            // Otherwise the release doesn't do anything and you get BadDrawable errors
 
464
            // when you come to delete the context.
 
465
            if (boundPixmap)
 
466
                QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
 
467
#endif
 
468
            glDeleteTextures(1, &id);
 
469
        }
 
470
     }
 
471
 
 
472
    QGLContext *context;
 
473
    GLuint id;
 
474
    GLenum target;
 
475
 
 
476
    QGLContext::BindOptions options;
 
477
 
 
478
#if defined(Q_WS_X11)
 
479
    QPixmapData* boundPixmap;
 
480
#endif
 
481
 
 
482
};
 
483
 
 
484
class QGLTextureCache {
 
485
public:
 
486
    QGLTextureCache();
 
487
    ~QGLTextureCache();
 
488
 
 
489
    void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
 
490
    void remove(quint64 key) { m_cache.remove(key); }
 
491
    bool remove(QGLContext *ctx, GLuint textureId);
 
492
    void removeContextTextures(QGLContext *ctx);
 
493
    int size() { return m_cache.size(); }
 
494
    void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); }
 
495
    int maxCost() {return m_cache.maxCost(); }
 
496
    QGLTexture* getTexture(quint64 key) { return m_cache.object(key); }
 
497
 
 
498
    static QGLTextureCache *instance();
 
499
    static void deleteIfEmpty();
 
500
    static void imageCleanupHook(qint64 cacheKey);
 
501
    static void pixmapCleanupHook(QPixmap* pixmap);
 
502
 
 
503
private:
 
504
    QCache<qint64, QGLTexture> m_cache;
 
505
};
 
506
 
 
507
 
373
508
#ifdef Q_WS_QWS
374
 
class QOpenGLPaintEngine;
375
 
extern QOpenGLPaintEngine* qt_qgl_paint_engine();
376
 
 
377
 
extern EGLDisplay qt_qgl_egl_display();
 
509
extern QPaintEngine* qt_qgl_paint_engine();
378
510
#endif
379
511
 
 
512
bool qt_gl_preferGL2Engine();
 
513
 
380
514
inline GLenum qt_gl_preferredTextureFormat()
381
515
{
382
516
    return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA;
384
518
 
385
519
inline GLenum qt_gl_preferredTextureTarget()
386
520
{
 
521
#if defined(QT_OPENGL_ES_2)
 
522
    return GL_TEXTURE_2D;
 
523
#else
387
524
    return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
 
525
           && !qt_gl_preferGL2Engine()
388
526
           ? GL_TEXTURE_RECTANGLE_NV
389
527
           : GL_TEXTURE_2D;
 
528
#endif
390
529
}
391
530
 
 
531
// One resource per group of shared contexts.
 
532
class Q_AUTOTEST_EXPORT QGLContextResource
 
533
{
 
534
public:
 
535
    typedef void (*FreeFunc)(void *);
 
536
    QGLContextResource(FreeFunc f);
 
537
    ~QGLContextResource();
 
538
    // Set resource 'value' for 'key' and all its shared contexts.
 
539
    void insert(const QGLContext *key, void *value);
 
540
    // Return resource for 'key' or a shared context.
 
541
    void *value(const QGLContext *key);
 
542
    // Cleanup 'value' in response to a context group being destroyed.
 
543
    void cleanup(const QGLContext *ctx, void *value);
 
544
private:
 
545
    FreeFunc free;
 
546
    QAtomicInt active;
 
547
};
 
548
 
 
549
// Put a guard around a GL object identifier and its context.
 
550
// When the context goes away, a shared context will be used
 
551
// in its place.  If there are no more shared contexts, then
 
552
// the identifier is returned as zero - it is assumed that the
 
553
// context destruction cleaned up the identifier in this case.
 
554
class Q_OPENGL_EXPORT QGLSharedResourceGuard
 
555
{
 
556
public:
 
557
    QGLSharedResourceGuard(const QGLContext *context)
 
558
        : m_group(0), m_id(0), m_next(0), m_prev(0)
 
559
    {
 
560
        setContext(context);
 
561
    }
 
562
    QGLSharedResourceGuard(const QGLContext *context, GLuint id)
 
563
        : m_group(0), m_id(id), m_next(0), m_prev(0)
 
564
    {
 
565
        setContext(context);
 
566
    }
 
567
    ~QGLSharedResourceGuard();
 
568
 
 
569
    const QGLContext *context() const
 
570
    {
 
571
        return m_group ? m_group->context() : 0;
 
572
    }
 
573
 
 
574
    void setContext(const QGLContext *context);
 
575
 
 
576
    GLuint id() const
 
577
    {
 
578
        return m_id;
 
579
    }
 
580
 
 
581
    void setId(GLuint id)
 
582
    {
 
583
        m_id = id;
 
584
    }
 
585
 
 
586
private:
 
587
    QGLContextGroup *m_group;
 
588
    GLuint m_id;
 
589
    QGLSharedResourceGuard *m_next;
 
590
    QGLSharedResourceGuard *m_prev;
 
591
 
 
592
    friend class QGLContextGroup;
 
593
};
392
594
 
393
595
QT_END_NAMESPACE
394
596