1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 ** This file is part of the QtOpenGL module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** 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.
40 ****************************************************************************/
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.
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 "private/qwidget_p.h"
64 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
65 #include "private/qpixmapdata_gl_p.h"
68 #ifndef QT_OPENGL_ES_1_CL
69 #define q_vertexType float
70 #define q_vertexTypeEnum GL_FLOAT
73 #define i2vt(i) (float(i))
75 #define FLOAT2X(f) (int( (f) * (65536)))
76 #define X2FLOAT(x) (float(x) / 65536.0f)
77 #define f2vt(f) FLOAT2X(f)
78 #define i2vt(i) ((i)*65536)
79 #define vt2f(x) X2FLOAT(x)
80 #define q_vertexType GLfixed
81 #define q_vertexTypeEnum GL_FIXED
82 #endif //QT_OPENGL_ES_1_CL
85 QT_BEGIN_INCLUDE_NAMESPACE
86 #if defined(QT_OPENGL_ES_2)
91 QT_END_INCLUDE_NAMESPACE
97 class QGLOverlayWidget
;
102 # define old_qDebug qDebug
105 QT_BEGIN_INCLUDE_NAMESPACE
106 #ifndef QT_MAC_USE_COCOA
107 # include <AGL/agl.h>
109 QT_END_INCLUDE_NAMESPACE
112 # define qDebug QT_QDEBUG_MACRO
115 class QMacWindowChangeEvent
;
119 class QWSGLWindowSurface
;
122 #if defined(QT_OPENGL_ES)
126 QT_BEGIN_INCLUDE_NAMESPACE
127 #include <QtOpenGL/private/qglextensions_p.h>
128 QT_END_INCLUDE_NAMESPACE
130 class QGLFormatPrivate
134 opts
= QGL::DoubleBuffer
| QGL::DepthBuffer
| QGL::Rgba
| QGL::DirectRendering
| QGL::StencilBuffer
;
135 #if defined(QT_OPENGL_ES_2)
136 opts
|= QGL::SampleBuffers
;
139 depthSize
= accumSize
= stencilSize
= redSize
= greenSize
= blueSize
= alphaSize
= -1;
143 QGL::FormatOptions opts
;
156 class QGLWidgetPrivate
: public QWidgetPrivate
158 Q_DECLARE_PUBLIC(QGLWidget
)
160 QGLWidgetPrivate() : QWidgetPrivate()
164 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES)
165 , eglSurfaceWindowId(0)
169 ~QGLWidgetPrivate() {}
171 void init(QGLContext
*context
, const QGLWidget
* shareWidget
);
172 void initContext(QGLContext
*context
, const QGLWidget
* shareWidget
);
173 bool renderCxPm(QPixmap
*pixmap
);
174 void cleanupColormaps();
180 QMap
<QString
, int> displayListCache
;
182 #if defined(Q_WS_WIN)
183 void updateColormap();
185 #elif defined(Q_WS_X11)
186 QGLOverlayWidget
*olw
;
187 #if defined(QT_OPENGL_ES)
188 void recreateEglSurface(bool force
);
189 WId eglSurfaceWindowId
;
191 #elif defined(Q_WS_MAC)
193 void updatePaintDevice();
194 #elif defined(Q_WS_QWS)
195 QWSGLWindowSurface
*wsurf
;
199 class QGLContextPrivate
201 Q_DECLARE_PUBLIC(QGLContext
)
203 explicit QGLContextPrivate(QGLContext
*context
) : internal_context(false), q_ptr(context
) {}
204 ~QGLContextPrivate() {}
205 GLuint
bindTexture(const QImage
&image
, GLenum target
, GLint format
, const qint64 key
,
207 GLuint
bindTexture(const QPixmap
&pixmap
, GLenum target
, GLint format
, bool clean
);
208 GLuint
bindTexture(const QImage
&image
, GLenum target
, GLint format
, bool clean
);
209 bool textureCacheLookup(const qint64 key
, GLenum target
, GLuint
*id
);
210 void init(QPaintDevice
*dev
, const QGLFormat
&format
);
211 QImage
convertToGLFormat(const QImage
&image
, bool force_premul
, GLenum texture_format
);
212 int maxTextureSize();
216 #if defined(Q_WS_WIN)
225 #if defined(QT_OPENGL_ES)
226 QEglContext
*eglContext
;
227 #elif defined(Q_WS_X11) || defined(Q_WS_MAC)
230 #if defined(Q_WS_X11) || defined(Q_WS_MAC)
233 #if defined(Q_WS_X11)
238 #if defined(Q_WS_MAC)
240 void *tryFormat(const QGLFormat
&format
);
241 void clearDrawable();
252 uint clear_on_painter_begin
: 1;
253 uint internal_context
: 1;
254 uint version_flags_cached
: 1;
255 QPaintDevice
*paintDevice
;
258 QGLFormat::OpenGLVersionFlags version_flags
;
260 QGLExtensionFuncs extensionFuncs
;
261 GLint max_texture_size
;
264 QPaintEngine
*active_engine
;
267 static inline QGLExtensionFuncs
& qt_get_extension_funcs(const QGLContext
*ctx
) { return ctx
->d_ptr
->extensionFuncs
; }
270 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
271 static QGLExtensionFuncs qt_extensionFuncs
;
272 static inline QGLExtensionFuncs
& qt_get_extension_funcs(const QGLContext
*) { return qt_extensionFuncs
; }
275 QPixmapFilter
*createPixmapFilter(int type
) const;
278 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff
279 class Q_OPENGL_EXPORT QGLSignalProxy
: public QObject
283 QGLSignalProxy() : QObject() {}
284 void emitAboutToDestroyContext(const QGLContext
*context
) {
285 emit
aboutToDestroyContext(context
);
287 static QGLSignalProxy
*instance();
289 void aboutToDestroyContext(const QGLContext
*context
);
292 class QGLPixelBuffer
;
293 class QGLFramebufferObject
;
294 class QWSGLWindowSurface
;
295 class QGLWindowSurface
;
298 QGLDrawable() : widget(0), buffer(0), fbo(0)
299 #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
302 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
306 void setDevice(QPaintDevice
*pdev
);
311 QGLFormat
format() const;
312 GLuint
bindTexture(const QImage
&image
, GLenum target
= GL_TEXTURE_2D
, GLint format
= GL_RGBA
);
313 GLuint
bindTexture(const QPixmap
&pixmap
, GLenum target
= GL_TEXTURE_2D
, GLint format
= GL_RGBA
);
314 QColor
backgroundColor() const;
315 QGLContext
*context() const;
316 bool autoFillBackground() const;
317 bool hasTransparentBackground() const;
319 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
320 QGLPixmapData
*copyOnBegin() const;
326 QGLPixelBuffer
*buffer
;
327 QGLFramebufferObject
*fbo
;
329 QWSGLWindowSurface
*wsurf
;
330 #elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
331 QGLWindowSurface
*wsurf
;
334 #if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
335 QGLPixmapData
*pixmapData
;
340 // GL extension definitions
341 class QGLExtensions
{
344 TextureRectangle
= 0x00000001,
345 SampleBuffers
= 0x00000002,
346 GenerateMipmap
= 0x00000004,
347 TextureCompression
= 0x00000008,
348 FragmentProgram
= 0x00000010,
349 MirroredRepeat
= 0x00000020,
350 FramebufferObject
= 0x00000040,
351 StencilTwoSide
= 0x00000080,
352 StencilWrap
= 0x00000100,
353 PackedDepthStencil
= 0x00000200,
354 NVFloatBuffer
= 0x00000400,
355 PixelBufferObject
= 0x00000800,
356 FramebufferBlit
= 0x00001000
358 Q_DECLARE_FLAGS(Extensions
, Extension
)
360 static Extensions glExtensions
;
361 static bool nvidiaFboNeedsFinish
;
362 static void init(); // sys dependent
363 static void init_extensions(); // general: called by init()
366 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions
)
369 struct QGLThreadContext
{
372 extern QThreadStorage
<QGLThreadContext
*> qgl_context_storage
;
374 typedef QMultiHash
<const QGLContext
*, const QGLContext
*> QGLSharingHash
;
375 class QGLShareRegister
378 QGLShareRegister() {}
379 ~QGLShareRegister() { reg
.clear(); }
381 bool checkSharing(const QGLContext
*context1
, const QGLContext
*context2
, const QGLContext
* skip
=0) {
382 if (context1
== context2
)
384 QList
<const QGLContext
*> shares
= reg
.values(context1
);
385 for (int k
=0; k
<shares
.size(); ++k
) {
386 const QGLContext
*ctx
= shares
.at(k
);
387 if (ctx
== skip
) // avoid an indirect circular loop (infinite recursion)
391 if (checkSharing(ctx
, context2
, context1
))
397 void addShare(const QGLContext
*context
, const QGLContext
*share
) {
398 reg
.insert(context
, share
); // context sharing works both ways
399 reg
.insert(share
, context
);
402 void removeShare(const QGLContext
*context
) {
403 QGLSharingHash::iterator it
= reg
.begin();
404 while (it
!= reg
.end()) {
405 if (it
.key() == context
|| it
.value() == context
)
412 void replaceShare(const QGLContext
*oldContext
, const QGLContext
*newContext
) {
413 QGLSharingHash::iterator it
= reg
.begin();
414 while (it
!= reg
.end()) {
415 if (it
.key() == oldContext
)
416 reg
.insert(newContext
, it
.value());
417 else if (it
.value() == oldContext
)
418 reg
.insert(it
.key(), newContext
);
421 removeShare(oldContext
);
428 extern Q_OPENGL_EXPORT QGLShareRegister
* qgl_share_reg();
431 extern QPaintEngine
* qt_qgl_paint_engine();
433 extern EGLDisplay
qt_qgl_egl_display();
436 inline bool qt_gl_preferGL2Engine()
438 #if defined(QT_OPENGL_ES_2)
441 return (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0
)
442 && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty();
446 inline GLenum
qt_gl_preferredTextureFormat()
448 return QSysInfo::ByteOrder
== QSysInfo::BigEndian
? GL_RGBA
: GL_BGRA
;
451 inline GLenum
qt_gl_preferredTextureTarget()
453 #if defined(QT_OPENGL_ES_2)
454 return GL_TEXTURE_2D
;
456 return (QGLExtensions::glExtensions
& QGLExtensions::TextureRectangle
)
457 && !qt_gl_preferGL2Engine()
458 ? GL_TEXTURE_RECTANGLE_NV