1
1
/****************************************************************************
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)
6
7
** This file is part of the QtOpenGL module of the Qt Toolkit.
8
9
** $QT_BEGIN_LICENSE:LGPL$
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
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.
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
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.
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.
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
38
38
** $QT_END_LICENSE$
40
40
****************************************************************************/
222
class QGLContextResource;
223
class QGLSharedResourceGuard;
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
234
QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
235
const QGLContext *context() const {return m_context;}
237
void addGuard(QGLSharedResourceGuard *guard);
238
void removeGuard(QGLSharedResourceGuard *guard);
240
QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
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.
249
void cleanupResources(const QGLContext *ctx);
251
friend class QGLShareRegister;
252
friend class QGLContext;
253
friend class QGLContextPrivate;
254
friend class QGLContextResource;
195
259
class QGLContextPrivate
197
261
Q_DECLARE_PUBLIC(QGLContext)
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,
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();
252
323
QGLContext *q_ptr;
253
324
QGLFormat::OpenGLVersionFlags version_flags;
255
QGLExtensionFuncs extensionFuncs;
326
QGLContextGroup *group;
256
327
GLint max_texture_size;
330
QPaintEngine *active_engine;
332
static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
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(); }
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; }
267
QPixmapFilter *createPixmapFilter(int type) const;
343
static void setCurrentContext(QGLContext *context);
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
309
387
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
312
struct QGLThreadContext {
315
extern QThreadStorage<QGLThreadContext *> qgl_context_storage;
317
typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash;
318
class QGLShareRegister
390
class Q_AUTOTEST_EXPORT QGLShareRegister
321
393
QGLShareRegister() {}
322
~QGLShareRegister() { reg.clear(); }
324
bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) {
325
if (context1 == context2)
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)
334
if (checkSharing(ctx, context2, context1))
340
void addShare(const QGLContext *context, const QGLContext *share) {
341
reg.insert(context, share); // context sharing works both ways
342
reg.insert(share, context);
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)
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);
364
removeShare(oldContext);
394
~QGLShareRegister() {}
396
void addShare(const QGLContext *context, const QGLContext *share);
397
QList<const QGLContext *> shares(const QGLContext *context);
398
void removeShare(const QGLContext *context);
371
401
extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
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
409
QGLShareContextScope(const QGLContext *ctx)
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();
418
m_ctx = currentContext;
422
operator QGLContext *()
427
QGLContext *operator->()
432
~QGLShareContextScope()
435
m_oldContext->makeCurrent();
439
QGLContext *m_oldContext;
445
QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
446
QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
451
#if defined(Q_WS_X11)
457
if (options & QGLContext::MemoryManagedBindOption) {
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.
466
QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
468
glDeleteTextures(1, &id);
476
QGLContext::BindOptions options;
478
#if defined(Q_WS_X11)
479
QPixmapData* boundPixmap;
484
class QGLTextureCache {
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); }
498
static QGLTextureCache *instance();
499
static void deleteIfEmpty();
500
static void imageCleanupHook(qint64 cacheKey);
501
static void pixmapCleanupHook(QPixmap* pixmap);
504
QCache<qint64, QGLTexture> m_cache;
374
class QOpenGLPaintEngine;
375
extern QOpenGLPaintEngine* qt_qgl_paint_engine();
377
extern EGLDisplay qt_qgl_egl_display();
509
extern QPaintEngine* qt_qgl_paint_engine();
512
bool qt_gl_preferGL2Engine();
380
514
inline GLenum qt_gl_preferredTextureFormat()
382
516
return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA;
385
519
inline GLenum qt_gl_preferredTextureTarget()
521
#if defined(QT_OPENGL_ES_2)
522
return GL_TEXTURE_2D;
387
524
return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
525
&& !qt_gl_preferGL2Engine()
388
526
? GL_TEXTURE_RECTANGLE_NV
531
// One resource per group of shared contexts.
532
class Q_AUTOTEST_EXPORT QGLContextResource
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);
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
557
QGLSharedResourceGuard(const QGLContext *context)
558
: m_group(0), m_id(0), m_next(0), m_prev(0)
562
QGLSharedResourceGuard(const QGLContext *context, GLuint id)
563
: m_group(0), m_id(id), m_next(0), m_prev(0)
567
~QGLSharedResourceGuard();
569
const QGLContext *context() const
571
return m_group ? m_group->context() : 0;
574
void setContext(const QGLContext *context);
581
void setId(GLuint id)
587
QGLContextGroup *m_group;
589
QGLSharedResourceGuard *m_next;
590
QGLSharedResourceGuard *m_prev;
592
friend class QGLContextGroup;