source: trunk/src/opengl/qgl_p.h@ 780

Last change on this file since 780 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 20.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
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** 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 have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QGL_P_H
43#define QGL_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists for the convenience
50// of the QGLWidget class. This header file may change from
51// version to version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include "QtOpenGL/qgl.h"
57#include "QtOpenGL/qglcolormap.h"
58#include "QtCore/qmap.h"
59#include "QtCore/qthread.h"
60#include "QtCore/qthreadstorage.h"
61#include "QtCore/qhash.h"
62#include "QtCore/qatomic.h"
63#include "private/qwidget_p.h"
64#include "qcache.h"
65#include "qglpaintdevice_p.h"
66
67#ifndef QT_OPENGL_ES_1_CL
68#define q_vertexType float
69#define q_vertexTypeEnum GL_FLOAT
70#define f2vt(f) (f)
71#define vt2f(x) (x)
72#define i2vt(i) (float(i))
73#else
74#define FLOAT2X(f) (int( (f) * (65536)))
75#define X2FLOAT(x) (float(x) / 65536.0f)
76#define f2vt(f) FLOAT2X(f)
77#define i2vt(i) ((i)*65536)
78#define vt2f(x) X2FLOAT(x)
79#define q_vertexType GLfixed
80#define q_vertexTypeEnum GL_FIXED
81#endif //QT_OPENGL_ES_1_CL
82
83#if defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
84QT_BEGIN_INCLUDE_NAMESPACE
85
86#if defined(QT_OPENGL_ES_2)
87# include <GLES2/gl2.h>
88#endif
89
90#if defined(QT_GLES_EGL)
91# include <GLES/egl.h>
92#else
93# include <EGL/egl.h>
94#endif
95
96QT_END_INCLUDE_NAMESPACE
97#endif
98
99QT_BEGIN_NAMESPACE
100
101class QGLContext;
102class QGLOverlayWidget;
103class QPixmap;
104class QPixmapFilter;
105#ifdef Q_WS_MAC
106# ifdef qDebug
107# define old_qDebug qDebug
108# undef qDebug
109# endif
110QT_BEGIN_INCLUDE_NAMESPACE
111#ifndef QT_MAC_USE_COCOA
112# include <AGL/agl.h>
113#endif
114QT_END_INCLUDE_NAMESPACE
115# ifdef old_qDebug
116# undef qDebug
117# define qDebug QT_QDEBUG_MACRO
118# undef old_qDebug
119# endif
120class QMacWindowChangeEvent;
121#endif
122
123#ifdef Q_WS_QWS
124class QWSGLWindowSurface;
125#endif
126
127#if defined(QT_OPENGL_ES)
128class QEglContext;
129#endif
130
131QT_BEGIN_INCLUDE_NAMESPACE
132#include <QtOpenGL/private/qglextensions_p.h>
133QT_END_INCLUDE_NAMESPACE
134
135class QGLFormatPrivate
136{
137public:
138 QGLFormatPrivate()
139 : ref(1)
140 {
141 opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering | QGL::StencilBuffer;
142 pln = 0;
143 depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
144 numSamples = -1;
145 swapInterval = -1;
146 }
147 QGLFormatPrivate(const QGLFormatPrivate *other)
148 : ref(1),
149 opts(other->opts),
150 pln(other->pln),
151 depthSize(other->depthSize),
152 accumSize(other->accumSize),
153 stencilSize(other->stencilSize),
154 redSize(other->redSize),
155 greenSize(other->greenSize),
156 blueSize(other->blueSize),
157 alphaSize(other->alphaSize),
158 numSamples(other->numSamples),
159 swapInterval(other->swapInterval)
160 {
161 }
162 QAtomicInt ref;
163 QGL::FormatOptions opts;
164 int pln;
165 int depthSize;
166 int accumSize;
167 int stencilSize;
168 int redSize;
169 int greenSize;
170 int blueSize;
171 int alphaSize;
172 int numSamples;
173 int swapInterval;
174};
175
176class QGLWidgetPrivate : public QWidgetPrivate
177{
178 Q_DECLARE_PUBLIC(QGLWidget)
179public:
180 QGLWidgetPrivate() : QWidgetPrivate()
181 , disable_clear_on_painter_begin(false)
182#ifdef Q_WS_QWS
183 , wsurf(0)
184#endif
185#if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
186 , eglSurfaceWindowId(0)
187#endif
188 {
189 isGLWidget = 1;
190 }
191
192 ~QGLWidgetPrivate() {}
193
194 void init(QGLContext *context, const QGLWidget* shareWidget);
195 void initContext(QGLContext *context, const QGLWidget* shareWidget);
196 bool renderCxPm(QPixmap *pixmap);
197 void cleanupColormaps();
198
199 QGLContext *glcx;
200 QGLWidgetGLPaintDevice glDevice;
201 bool autoSwap;
202
203 QGLColormap cmap;
204#ifndef QT_OPENGL_ES
205 QMap<QString, int> displayListCache;
206#endif
207
208 bool disable_clear_on_painter_begin;
209
210#if defined(Q_WS_WIN)
211 void updateColormap();
212 QGLContext *olcx;
213#elif defined(Q_WS_X11)
214 QGLOverlayWidget *olw;
215#if defined(QT_OPENGL_ES)
216 void recreateEglSurface(bool force);
217 WId eglSurfaceWindowId;
218#endif
219#elif defined(Q_WS_MAC)
220 QGLContext *olcx;
221 void updatePaintDevice();
222#elif defined(Q_WS_QWS)
223 QWSGLWindowSurface *wsurf;
224#endif
225};
226
227class QGLContextResource;
228class QGLSharedResourceGuard;
229
230typedef QHash<QString, GLuint> QGLDDSCache;
231
232// QGLContextPrivate has the responsibility of creating context groups.
233// QGLContextPrivate maintains the reference counter and destroys
234// context groups when needed.
235class QGLContextGroup
236{
237public:
238 ~QGLContextGroup();
239
240 QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
241 const QGLContext *context() const {return m_context;}
242 bool isSharing() const { return m_shares.size() >= 2; }
243 QList<const QGLContext *> shares() const { return m_shares; }
244
245 void addGuard(QGLSharedResourceGuard *guard);
246 void removeGuard(QGLSharedResourceGuard *guard);
247
248 static void addShare(const QGLContext *context, const QGLContext *share);
249 static void removeShare(const QGLContext *context);
250private:
251 QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
252
253 QGLExtensionFuncs m_extensionFuncs;
254 const QGLContext *m_context; // context group's representative
255 QList<const QGLContext *> m_shares;
256 QHash<QGLContextResource *, void *> m_resources;
257 QGLSharedResourceGuard *m_guards; // double-linked list of active guards.
258 QAtomicInt m_refs;
259 QGLDDSCache m_dds_cache;
260
261 void cleanupResources(const QGLContext *ctx);
262
263 friend class QGLContext;
264 friend class QGLContextPrivate;
265 friend class QGLContextResource;
266};
267
268// Get the context that resources for "ctx" will transfer to once
269// "ctx" is destroyed. Returns null if nothing is sharing with ctx.
270Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
271
272// GL extension definitions
273class QGLExtensions {
274public:
275 enum Extension {
276 TextureRectangle = 0x00000001,
277 SampleBuffers = 0x00000002,
278 GenerateMipmap = 0x00000004,
279 TextureCompression = 0x00000008,
280 FragmentProgram = 0x00000010,
281 MirroredRepeat = 0x00000020,
282 FramebufferObject = 0x00000040,
283 StencilTwoSide = 0x00000080,
284 StencilWrap = 0x00000100,
285 PackedDepthStencil = 0x00000200,
286 NVFloatBuffer = 0x00000400,
287 PixelBufferObject = 0x00000800,
288 FramebufferBlit = 0x00001000,
289 NPOTTextures = 0x00002000,
290 BGRATextureFormat = 0x00004000,
291 DDSTextureCompression = 0x00008000,
292 ETC1TextureCompression = 0x00010000,
293 PVRTCTextureCompression = 0x00020000,
294 FragmentShader = 0x00040000
295 };
296 Q_DECLARE_FLAGS(Extensions, Extension)
297
298 static Extensions glExtensions();
299
300private:
301 static Extensions currentContextExtensions();
302};
303
304/*
305 QGLTemporaryContext - the main objective of this class is to have a way of
306 creating a GL context and making it current, without going via QGLWidget
307 and friends. At certain points during GL initialization we need a current
308 context in order decide what GL features are available, and to resolve GL
309 extensions. Having a light-weight way of creating such a context saves
310 initial application startup time, and it doesn't wind up creating recursive
311 conflicts.
312 The class currently uses a private d pointer to hide the platform specific
313 types. This could possibly been done inline with #ifdef'ery, but it causes
314 major headaches on e.g. X11 due to namespace pollution.
315*/
316class QGLTemporaryContextPrivate;
317class QGLTemporaryContext {
318public:
319 QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
320 ~QGLTemporaryContext();
321
322private:
323 QScopedPointer<QGLTemporaryContextPrivate> d;
324};
325
326class QGLTexture;
327
328// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
329// all the GL2 engine uses:
330#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
331
332class QGLContextPrivate
333{
334 Q_DECLARE_PUBLIC(QGLContext)
335public:
336 explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
337 ~QGLContextPrivate();
338 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
339 QGLContext::BindOptions options);
340 QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
341 QGLContext::BindOptions options);
342 QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
343 QGLContext::BindOptions options);
344 QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
345 void init(QPaintDevice *dev, const QGLFormat &format);
346 QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
347 int maxTextureSize();
348
349 void cleanup();
350
351 void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
352 void syncGlState(); // Makes sure the GL context's state is what we think it is
353
354#if defined(Q_WS_WIN)
355 HGLRC rc;
356 HDC dc;
357 WId win;
358 int pixelFormatId;
359 QGLCmap* cmap;
360 HBITMAP hbitmap;
361 HDC hbitmap_hdc;
362#endif
363#if defined(QT_OPENGL_ES)
364 QEglContext *eglContext;
365 EGLSurface eglSurface;
366 void destroyEglSurfaceForDevice();
367#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
368 void* cx;
369#endif
370#if defined(Q_WS_X11) || defined(Q_WS_MAC)
371 void* vi;
372#endif
373#if defined(Q_WS_X11)
374 void* pbuf;
375 quint32 gpm;
376 int screen;
377 QHash<QPixmapData*, QPixmap> boundPixmaps;
378 QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
379 QGLContext::BindOptions options);
380 static void destroyGlSurfaceForPixmap(QPixmapData*);
381 static void unbindPixmapFromTexture(QPixmapData*);
382#endif
383#if defined(Q_WS_MAC)
384 bool update;
385 void *tryFormat(const QGLFormat &format);
386 void clearDrawable();
387#endif
388 QGLFormat glFormat;
389 QGLFormat reqFormat;
390 GLuint fbo;
391
392 uint valid : 1;
393 uint sharing : 1;
394 uint initDone : 1;
395 uint crWin : 1;
396 uint internal_context : 1;
397 uint version_flags_cached : 1;
398 uint extension_flags_cached : 1;
399 QPaintDevice *paintDevice;
400 QColor transpColor;
401 QGLContext *q_ptr;
402 QGLFormat::OpenGLVersionFlags version_flags;
403 QGLExtensions::Extensions extension_flags;
404
405 QGLContextGroup *group;
406 GLint max_texture_size;
407
408 GLuint current_fbo;
409 GLuint default_fbo;
410 QPaintEngine *active_engine;
411
412 bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
413
414 static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
415
416#ifdef Q_WS_WIN
417 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
418#endif
419
420#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
421 static QGLExtensionFuncs qt_extensionFuncs;
422 static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
423#endif
424
425 static void setCurrentContext(QGLContext *context);
426};
427
428// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
429class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
430{
431 Q_OBJECT
432public:
433 QGLSignalProxy() : QObject() {}
434 void emitAboutToDestroyContext(const QGLContext *context) {
435 emit aboutToDestroyContext(context);
436 }
437 static QGLSignalProxy *instance();
438Q_SIGNALS:
439 void aboutToDestroyContext(const QGLContext *context);
440};
441
442Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
443
444// Temporarily make a context current if not already current or
445// shared with the current contex. The previous context is made
446// current when the object goes out of scope.
447class Q_OPENGL_EXPORT QGLShareContextScope
448{
449public:
450 QGLShareContextScope(const QGLContext *ctx)
451 : m_oldContext(0)
452 {
453 QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
454 if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
455 m_oldContext = currentContext;
456 m_ctx = const_cast<QGLContext *>(ctx);
457 m_ctx->makeCurrent();
458 } else {
459 m_ctx = currentContext;
460 }
461 }
462
463 operator QGLContext *()
464 {
465 return m_ctx;
466 }
467
468 QGLContext *operator->()
469 {
470 return m_ctx;
471 }
472
473 ~QGLShareContextScope()
474 {
475 if (m_oldContext)
476 m_oldContext->makeCurrent();
477 }
478
479private:
480 QGLContext *m_oldContext;
481 QGLContext *m_ctx;
482};
483
484class QGLTexture {
485public:
486 QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
487 QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
488 : context(ctx),
489 id(tx_id),
490 target(tx_target),
491 options(opt)
492#if defined(Q_WS_X11)
493 , boundPixmap(0)
494#endif