summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /src/opengl
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/qgl.cpp2367
-rw-r--r--src/opengl/qgl.h541
-rw-r--r--src/opengl/qgl_x11.cpp1406
-rw-r--r--src/opengl/qgl_x11_p.h197
-rw-r--r--src/opengl/qglcolormap.cpp292
-rw-r--r--src/opengl/qglcolormap.h99
-rw-r--r--src/opengl/qt_opengl.pri18
7 files changed, 4920 insertions, 0 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
new file mode 100644
index 0000000..c2a35ea
--- /dev/null
+++ b/src/opengl/qgl.cpp
@@ -0,0 +1,2367 @@
+/****************************************************************************
+**
+** Implementation of OpenGL classes for Qt
+**
+** Created : 970112
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qgl.h"
+#include "qpixmap.h"
+#include "qpaintdevicemetrics.h"
+#include "qimage.h"
+#include "qcleanuphandler.h"
+#include "qptrdict.h"
+
+static QGLFormat* qgl_default_format = 0;
+static QGLFormat* qgl_default_overlay_format = 0;
+
+#if defined(Q_WS_X11)
+#include "private/qt_x11_p.h"
+#define INT32 dummy_INT32
+#define INT8 dummy_INT8
+#include <GL/glx.h>
+#undef INT32
+#undef INT8
+#include "qgl_x11_p.h"
+#endif
+
+static QCleanupHandler<QGLFormat> qgl_cleanup_format;
+
+
+/*!
+ \class QGL qgl.h
+ \brief The QGL class is a namespace for miscellaneous identifiers
+ in the Qt OpenGL module.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \module OpenGL
+ \ingroup graphics
+ \ingroup images
+
+
+ Normally you can ignore this class. QGLWidget and the other
+ OpenGL<sup>*</sup> module classes inherit it, so when you make your
+ own QGLWidget subclass you can use the identifiers in the QGL
+ namespace without qualification.
+
+ However, you may occasionally find yourself in situations where you
+ need to refer to these identifiers from outside the QGL namespace's
+ scope, e.g. in static functions. In such cases, simply write e.g. \c
+ QGL::DoubleBuffer instead of just \c DoubleBuffer.
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+
+*/
+
+
+/*****************************************************************************
+ QGLFormat implementation
+ *****************************************************************************/
+
+
+/*!
+ \class QGLFormat qgl.h
+ \brief The QGLFormat class specifies the display format of an OpenGL
+ rendering context.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \ingroup graphics
+ \ingroup images
+ \module OpenGL
+
+ A display format has several characteristics:
+ \list
+ \i \link setDoubleBuffer() Double or single buffering.\endlink
+ \i \link setDepth() Depth buffer.\endlink
+ \i \link setRgba() RGBA or color index mode.\endlink
+ \i \link setAlpha() Alpha channel.\endlink
+ \i \link setAccum() Accumulation buffer.\endlink
+ \i \link setStencil() Stencil buffer.\endlink
+ \i \link setStereo() Stereo buffers.\endlink
+ \i \link setDirectRendering() Direct rendering.\endlink
+ \i \link setOverlay() Presence of an overlay.\endlink
+ \i \link setPlane() The plane of an overlay format.\endlink
+ \endlist
+
+ You create and tell a QGLFormat object what rendering options you
+ want from an OpenGL<sup>*</sup> rendering context.
+
+ OpenGL drivers or accelerated hardware may or may not support
+ advanced features such as alpha channel or stereographic viewing.
+ If you request some features that the driver/hardware does not
+ provide when you create a QGLWidget, you will get a rendering
+ context with the nearest subset of features.
+
+ There are different ways to define the display characteristics of
+ a rendering context. One is to create a QGLFormat and make it the
+ default for the entire application:
+ \code
+ QGLFormat f;
+ f.setAlpha( TRUE );
+ f.setStereo( TRUE );
+ QGLFormat::setDefaultFormat( f );
+ \endcode
+
+ Or you can specify the desired format when creating an object of
+ your QGLWidget subclass:
+ \code
+ QGLFormat f;
+ f.setDoubleBuffer( FALSE ); // single buffer
+ f.setDirectRendering( FALSE ); // software rendering
+ MyGLWidget* myWidget = new MyGLWidget( f, ... );
+ \endcode
+
+ After the widget has been created, you can find out which of the
+ requested features the system was able to provide:
+ \code
+ QGLFormat f;
+ f.setOverlay( TRUE );
+ f.setStereo( TRUE );
+ MyGLWidget* myWidget = new MyGLWidget( f, ... );
+ if ( !w->format().stereo() ) {
+ // ok, goggles off
+ if ( !w->format().hasOverlay() ) {
+ qFatal( "Cool hardware required" );
+ }
+ }
+ \endcode
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+
+ \sa QGLContext, QGLWidget
+*/
+
+
+/*!
+ Constructs a QGLFormat object with the factory default settings:
+ \list
+ \i \link setDoubleBuffer() Double buffer:\endlink Enabled.
+ \i \link setDepth() Depth buffer:\endlink Enabled.
+ \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled).
+ \i \link setAlpha() Alpha channel:\endlink Disabled.
+ \i \link setAccum() Accumulator buffer:\endlink Disabled.
+ \i \link setStencil() Stencil buffer:\endlink Disabled.
+ \i \link setStereo() Stereo:\endlink Disabled.
+ \i \link setDirectRendering() Direct rendering:\endlink Enabled.
+ \i \link setOverlay() Overlay:\endlink Disabled.
+ \i \link setPlane() Plane:\endlink 0 (i.e., normal plane).
+ \endlist
+*/
+
+QGLFormat::QGLFormat()
+{
+ opts = DoubleBuffer | DepthBuffer | Rgba | DirectRendering;
+ pln = 0;
+}
+
+
+/*!
+ Creates a QGLFormat object that is a copy of the current \link
+ defaultFormat() application default format\endlink.
+
+ If \a options is not 0, this copy is modified by these format
+ options. The \a options parameter should be \c FormatOption values
+ OR'ed together.
+
+ This constructor makes it easy to specify a certain desired format
+ in classes derived from QGLWidget, for example:
+ \code
+ // The rendering in MyGLWidget depends on using
+ // stencil buffer and alpha channel
+ MyGLWidget::MyGLWidget( QWidget* parent, const char* name )
+ : QGLWidget( QGLFormat( StencilBuffer | AlphaChannel ), parent, name )
+ {
+ if ( !format().stencil() )
+ qWarning( "Could not get stencil buffer; results will be suboptimal" );
+ if ( !format().alphaChannel() )
+ qWarning( "Could not get alpha channel; results will be suboptimal" );
+ ...
+ }
+ \endcode
+
+ Note that there are \c FormatOption values to turn format settings
+ both on and off, e.g. \c DepthBuffer and \c NoDepthBuffer,
+ \c DirectRendering and \c IndirectRendering, etc.
+
+ The \a plane parameter defaults to 0 and is the plane which this
+ format should be associated with. Not all OpenGL implmentations
+ supports overlay/underlay rendering planes.
+
+ \sa defaultFormat(), setOption()
+*/
+
+QGLFormat::QGLFormat( int options, int plane )
+{
+ uint newOpts = options;
+ opts = defaultFormat().opts;
+ opts |= ( newOpts & 0xffff );
+ opts &= ~( newOpts >> 16 );
+ pln = plane;
+}
+
+
+/*!
+ \fn bool QGLFormat::doubleBuffer() const
+
+ Returns TRUE if double buffering is enabled; otherwise returns
+ FALSE. Double buffering is enabled by default.
+
+ \sa setDoubleBuffer()
+*/
+
+/*!
+ If \a enable is TRUE sets double buffering; otherwise sets single
+ buffering.
+
+ Double buffering is enabled by default.
+
+ Double buffering is a technique where graphics are rendered on an
+ off-screen buffer and not directly to the screen. When the drawing
+ has been completed, the program calls a swapBuffers() function to
+ exchange the screen contents with the buffer. The result is
+ flicker-free drawing and often better performance.
+
+ \sa doubleBuffer(), QGLContext::swapBuffers(),
+ QGLWidget::swapBuffers()
+*/
+
+void QGLFormat::setDoubleBuffer( bool enable )
+{
+ setOption( enable ? DoubleBuffer : SingleBuffer );
+}
+
+
+/*!
+ \fn bool QGLFormat::depth() const
+
+ Returns TRUE if the depth buffer is enabled; otherwise returns
+ FALSE. The depth buffer is enabled by default.
+
+ \sa setDepth()
+*/
+
+/*!
+ If \a enable is TRUE enables the depth buffer; otherwise disables
+ the depth buffer.
+
+ The depth buffer is enabled by default.
+
+ The purpose of a depth buffer (or Z-buffering) is to remove hidden
+ surfaces. Pixels are assigned Z values based on the distance to
+ the viewer. A pixel with a high Z value is closer to the viewer
+ than a pixel with a low Z value. This information is used to
+ decide whether to draw a pixel or not.
+
+ \sa depth()
+*/
+
+void QGLFormat::setDepth( bool enable )
+{
+ setOption( enable ? DepthBuffer : NoDepthBuffer );
+}
+
+
+/*!
+ \fn bool QGLFormat::rgba() const
+
+ Returns TRUE if RGBA color mode is set. Returns FALSE if color
+ index mode is set. The default color mode is RGBA.
+
+ \sa setRgba()
+*/
+
+/*!
+ If \a enable is TRUE sets RGBA mode. If \a enable is FALSE sets
+ color index mode.
+
+ The default color mode is RGBA.
+
+ RGBA is the preferred mode for most OpenGL applications. In RGBA
+ color mode you specify colors as red + green + blue + alpha
+ quadruplets.
+
+ In color index mode you specify an index into a color lookup
+ table.
+
+ \sa rgba()
+*/
+
+void QGLFormat::setRgba( bool enable )
+{
+ setOption( enable ? Rgba : ColorIndex );
+}
+
+
+/*!
+ \fn bool QGLFormat::alpha() const
+
+ Returns TRUE if the alpha channel of the framebuffer is enabled;
+ otherwise returns FALSE. The alpha channel is disabled by default.
+
+ \sa setAlpha()
+*/
+
+/*!
+ If \a enable is TRUE enables the alpha channel; otherwise disables
+ the alpha channel.
+
+ The alpha buffer is disabled by default.
+
+ The alpha channel is typically used for implementing transparency
+ or translucency. The A in RGBA specifies the transparency of a
+ pixel.
+
+ \sa alpha()
+*/
+
+void QGLFormat::setAlpha( bool enable )
+{
+ setOption( enable ? AlphaChannel : NoAlphaChannel );
+}
+
+
+/*!
+ \fn bool QGLFormat::accum() const
+
+ Returns TRUE if the accumulation buffer is enabled; otherwise
+ returns FALSE. The accumulation buffer is disabled by default.
+
+ \sa setAccum()
+*/
+
+/*!
+ If \a enable is TRUE enables the accumulation buffer; otherwise
+ disables the accumulation buffer.
+
+ The accumulation buffer is disabled by default.
+
+ The accumulation buffer is used to create blur effects and
+ multiple exposures.
+
+ \sa accum()
+*/
+
+void QGLFormat::setAccum( bool enable )
+{
+ setOption( enable ? AccumBuffer : NoAccumBuffer );
+}
+
+
+/*!
+ \fn bool QGLFormat::stencil() const
+
+ Returns TRUE if the stencil buffer is enabled; otherwise returns
+ FALSE. The stencil buffer is disabled by default.
+
+ \sa setStencil()
+*/
+
+/*!
+ If \a enable is TRUE enables the stencil buffer; otherwise
+ disables the stencil buffer.
+
+ The stencil buffer is disabled by default.
+
+ The stencil buffer masks certain parts of the drawing area so that
+ masked parts are not drawn on.
+
+ \sa stencil()
+*/
+
+void QGLFormat::setStencil( bool enable )
+{
+ setOption( enable ? StencilBuffer: NoStencilBuffer );
+}
+
+
+/*!
+ \fn bool QGLFormat::stereo() const
+
+ Returns TRUE if stereo buffering is enabled; otherwise returns
+ FALSE. Stereo buffering is disabled by default.
+
+ \sa setStereo()
+*/
+
+/*!
+ If \a enable is TRUE enables stereo buffering; otherwise disables
+ stereo buffering.
+
+ Stereo buffering is disabled by default.
+
+ Stereo buffering provides extra color buffers to generate left-eye
+ and right-eye images.
+
+ \sa stereo()
+*/
+
+void QGLFormat::setStereo( bool enable )
+{
+ setOption( enable ? StereoBuffers : NoStereoBuffers );
+}
+
+
+/*!
+ \fn bool QGLFormat::directRendering() const
+
+ Returns TRUE if direct rendering is enabled; otherwise returns
+ FALSE.
+
+ Direct rendering is enabled by default.
+
+ \sa setDirectRendering()
+*/
+
+/*!
+ If \a enable is TRUE enables direct rendering; otherwise disables
+ direct rendering.
+
+ Direct rendering is enabled by default.
+
+ Enabling this option will make OpenGL bypass the underlying window
+ system and render directly from hardware to the screen, if this is
+ supported by the system.
+
+ \sa directRendering()
+*/
+
+void QGLFormat::setDirectRendering( bool enable )
+{
+ setOption( enable ? DirectRendering : IndirectRendering );
+}
+
+
+/*!
+ \fn bool QGLFormat::hasOverlay() const
+
+ Returns TRUE if overlay plane is enabled; otherwise returns FALSE.
+
+ Overlay is disabled by default.
+
+ \sa setOverlay()
+*/
+
+/*!
+ If \a enable is TRUE enables an overlay plane; otherwise disables
+ the overlay plane.
+
+ Enabling the overlay plane will cause QGLWidget to create an
+ additional context in an overlay plane. See the QGLWidget
+ documentation for further information.
+
+ \sa hasOverlay()
+*/
+
+void QGLFormat::setOverlay( bool enable )
+{
+ setOption( enable ? HasOverlay : NoOverlay );
+}
+
+/*!
+ Returns the plane of this format. The default for normal formats
+ is 0, which means the normal plane. The default for overlay
+ formats is 1, which is the first overlay plane.
+
+ \sa setPlane()
+*/
+int QGLFormat::plane() const
+{
+ return pln;
+}
+
+/*!
+ Sets the requested plane to \a plane. 0 is the normal plane, 1 is
+ the first overlay plane, 2 is the second overlay plane, etc.; -1,
+ -2, etc. are underlay planes.
+
+ Note that in contrast to other format specifications, the plane
+ specifications will be matched exactly. This means that if you
+ specify a plane that the underlying OpenGL system cannot provide,
+ an \link QGLWidget::isValid() invalid\endlink QGLWidget will be
+ created.
+
+ \sa plane()
+*/
+void QGLFormat::setPlane( int plane )
+{
+ pln = plane;
+}
+
+/*!
+ Sets the format option to \a opt.
+
+ \sa testOption()
+*/
+
+void QGLFormat::setOption( FormatOption opt )
+{
+ if ( opt & 0xffff )
+ opts |= opt;
+ else
+ opts &= ~( opt >> 16 );
+}
+
+
+
+/*!
+ Returns TRUE if format option \a opt is set; otherwise returns FALSE.
+
+ \sa setOption()
+*/
+
+bool QGLFormat::testOption( FormatOption opt ) const
+{
+ if ( opt & 0xffff )
+ return ( opts & opt ) != 0;
+ else
+ return ( opts & ( opt >> 16 ) ) == 0;
+}
+
+
+
+/*!
+ \fn bool QGLFormat::hasOpenGL()
+
+ Returns TRUE if the window system has any OpenGL support;
+ otherwise returns FALSE.
+
+ \warning This function must not be called until the QApplication
+ object has been created.
+*/
+
+
+
+/*!
+ \fn bool QGLFormat::hasOpenGLOverlays()
+
+ Returns TRUE if the window system supports OpenGL overlays;
+ otherwise returns FALSE.
+
+ \warning This function must not be called until the QApplication
+ object has been created.
+*/
+
+/*!
+ Returns the default QGLFormat for the application. All QGLWidgets
+ that are created use this format unless another format is
+ specified, e.g. when they are constructed.
+
+ If no special default format has been set using
+ setDefaultFormat(), the default format is the same as that created
+ with QGLFormat().
+
+ \sa setDefaultFormat()
+*/
+
+QGLFormat QGLFormat::defaultFormat()
+{
+ if ( !qgl_default_format ) {
+ qgl_default_format = new QGLFormat;
+ qgl_cleanup_format.add( &qgl_default_format );
+ }
+ return *qgl_default_format;
+}
+
+/*!
+ Sets a new default QGLFormat for the application to \a f. For
+ example, to set single buffering as the default instead of double
+ buffering, your main() might contain code like this:
+ \code
+ QApplication a(argc, argv);
+ QGLFormat f;
+ f.setDoubleBuffer( FALSE );
+ QGLFormat::setDefaultFormat( f );
+ \endcode
+
+ \sa defaultFormat()
+*/
+
+void QGLFormat::setDefaultFormat( const QGLFormat &f )
+{
+ if ( !qgl_default_format ) {
+ qgl_default_format = new QGLFormat;
+ qgl_cleanup_format.add( &qgl_default_format );
+ }
+ *qgl_default_format = f;
+}
+
+
+/*!
+ Returns the default QGLFormat for overlay contexts.
+
+ The factory default overlay format is:
+ \list
+ \i \link setDoubleBuffer() Double buffer:\endlink Disabled.
+ \i \link setDepth() Depth buffer:\endlink Disabled.
+ \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled).
+ \i \link setAlpha() Alpha channel:\endlink Disabled.
+ \i \link setAccum() Accumulator buffer:\endlink Disabled.
+ \i \link setStencil() Stencil buffer:\endlink Disabled.
+ \i \link setStereo() Stereo:\endlink Disabled.
+ \i \link setDirectRendering() Direct rendering:\endlink Enabled.
+ \i \link setOverlay() Overlay:\endlink Disabled.
+ \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane).
+ \endlist
+
+ \sa setDefaultFormat()
+*/
+
+QGLFormat QGLFormat::defaultOverlayFormat()
+{
+ if ( !qgl_default_overlay_format ) {
+ qgl_default_overlay_format = new QGLFormat;
+ qgl_default_overlay_format->opts = DirectRendering;
+ qgl_default_overlay_format->pln = 1;
+ qgl_cleanup_format.add( &qgl_default_overlay_format );
+ }
+ return *qgl_default_overlay_format;
+}
+
+/*!
+ Sets a new default QGLFormat for overlay contexts to \a f. This
+ format is used whenever a QGLWidget is created with a format that
+ hasOverlay() enabled.
+
+ For example, to get a double buffered overlay context (if
+ available), use code like this:
+
+ \code
+ QGLFormat f = QGLFormat::defaultOverlayFormat();
+ f.setDoubleBuffer( TRUE );
+ QGLFormat::setDefaultOverlayFormat( f );
+ \endcode
+
+ As usual, you can find out after widget creation whether the
+ underlying OpenGL system was able to provide the requested
+ specification:
+
+ \code
+ // ...continued from above
+ MyGLWidget* myWidget = new MyGLWidget( QGLFormat( QGL::HasOverlay ), ... );
+ if ( myWidget->format().hasOverlay() ) {
+ // Yes, we got an overlay, let's check _its_ format:
+ QGLContext* olContext = myWidget->overlayContext();
+ if ( olContext->format().doubleBuffer() )
+ ; // yes, we got a double buffered overlay
+ else
+ ; // no, only single buffered overlays are available
+ }
+ \endcode
+
+ \sa defaultOverlayFormat()
+*/
+
+void QGLFormat::setDefaultOverlayFormat( const QGLFormat &f )
+{
+ if ( !qgl_default_overlay_format ) {
+ qgl_default_overlay_format = new QGLFormat;
+ qgl_cleanup_format.add( &qgl_default_overlay_format );
+ }
+ *qgl_default_overlay_format = f;
+ // Make sure the user doesn't request that the overlays themselves
+ // have overlays, since it is unlikely that the system supports
+ // infinitely many planes...
+ qgl_default_overlay_format->setOverlay( FALSE );
+}
+
+
+/*!
+ Returns TRUE if all the options of the two QGLFormats are equal;
+ otherwise returns FALSE.
+*/
+
+bool operator==( const QGLFormat& a, const QGLFormat& b )
+{
+ return (a.opts == b.opts) && (a.pln == b.pln);
+}
+
+
+/*!
+ Returns FALSE if all the options of the two QGLFormats are equal;
+ otherwise returns TRUE.
+*/
+
+bool operator!=( const QGLFormat& a, const QGLFormat& b )
+{
+ return !( a == b );
+}
+
+
+
+/*****************************************************************************
+ QGLContext implementation
+ *****************************************************************************/
+
+QGLContext* QGLContext::currentCtx = 0;
+
+/*!
+ \class QGLContext qgl.h
+ \brief The QGLContext class encapsulates an OpenGL rendering context.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \ingroup graphics
+ \ingroup images
+ \module OpenGL
+
+ An OpenGL<sup>*</sup> rendering context is a complete set of
+ OpenGL state variables.
+
+ The context's \link QGL::FormatOption format\endlink is set in the
+ constructor or later with setFormat(). The format options that are
+ actually set are returned by format(); the options you asked for
+ are returned by requestedFormat(). Note that after a QGLContext
+ object has been constructed, the actual OpenGL context must be
+ created by explicitly calling the \link create() create()\endlink
+ function. The makeCurrent() function makes this context the
+ current rendering context. You can make \e no context current
+ using doneCurrent(). The reset() function will reset the context
+ and make it invalid.
+
+ You can examine properties of the context with, e.g. isValid(),
+ isSharing(), initialized(), windowCreated() and
+ overlayTransparentColor().
+
+ If you're using double buffering you can swap the screen contents
+ with the off-screen buffer using swapBuffers().
+
+ Please note that QGLContext is not thread safe.
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+
+*/
+
+
+/*!
+ Constructs an OpenGL context for the paint device \a device, which
+ can be a widget or a pixmap. The \a format specifies several
+ display options for the context.
+
+ If the underlying OpenGL/Window system cannot satisfy all the
+ features requested in \a format, the nearest subset of features
+ will be used. After creation, the format() method will return the
+ actual format obtained.
+
+ Note that after a QGLContext object has been constructed, \link
+ create() create()\endlink must be called explicitly to create
+ the actual OpenGL context. The context will be \link isValid()
+ invalid\endlink if it was not possible to obtain a GL context at
+ all.
+
+ \sa format(), isValid()
+*/
+
+QGLContext::QGLContext( const QGLFormat &format, QPaintDevice *device )
+ : glFormat(format), reqFormat(format)
+{
+ init( device );
+}
+
+/*!
+ \overload
+ \internal
+*/
+QGLContext::QGLContext( const QGLFormat &format )
+ : glFormat( format ), reqFormat(format)
+{
+ init();
+}
+
+/*!
+ Destroys the OpenGL context and frees its resources.
+*/
+
+QGLContext::~QGLContext()
+{
+ reset();
+ if ( d )
+ delete d;
+}
+
+
+/*!
+ \fn QGLFormat QGLContext::format() const
+
+ Returns the frame buffer format that was obtained (this may be a
+ subset of what was requested).
+
+ \sa requestedFormat()
+*/
+
+/*!
+ \fn QGLFormat QGLContext::requestedFormat() const
+
+ Returns the frame buffer format that was originally requested in
+ the constructor or setFormat().
+
+ \sa format()
+*/
+
+/*!
+ Sets a \a format for this context. The context is \link reset()
+ reset\endlink.
+
+ Call create() to create a new GL context that tries to match the
+ new format.
+
+ \code
+ QGLContext *cx;
+ // ...
+ QGLFormat f;
+ f.setStereo( TRUE );
+ cx->setFormat( f );
+ if ( !cx->create() )
+ exit(); // no OpenGL support, or cannot render on the specified paintdevice
+ if ( !cx->format().stereo() )
+ exit(); // could not create stereo context
+ \endcode
+
+ \sa format(), reset(), create()
+*/
+
+void QGLContext::setFormat( const QGLFormat &format )
+{
+ reset();
+ glFormat = reqFormat = format;
+}
+
+/*!
+ \internal
+*/
+void QGLContext::setDevice( QPaintDevice *pDev )
+{
+ if ( isValid() )
+ reset();
+ d->paintDevice = pDev;
+ if ( d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
+ && d->paintDevice->devType() != QInternal::Pixmap) ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QGLContext: Unsupported paint device type" );
+#endif
+ }
+}
+
+void QGLContext::init( QPaintDevice *dev )
+{
+ d = new Private;
+ d->valid = FALSE;
+#if defined(Q_WS_X11)
+ qt_resolve_gl_symbols();
+ gpm = 0;
+#endif
+ setDevice( dev );
+#if defined(Q_WS_WIN)
+ dc = 0;
+ win = 0;
+ pixelFormatId = 0;
+ cmap = 0;
+#endif
+#if defined(Q_WS_MAC)
+ d->oldR = QRect(1, 1, 1, 1);
+#endif
+ d->crWin = FALSE;
+ d->initDone = FALSE;
+ d->sharing = FALSE;
+}
+
+/*!
+ \fn bool QGLContext::isValid() const
+
+ Returns TRUE if a GL rendering context has been successfully
+ created; otherwise returns FALSE.
+*/
+
+/*!
+ \fn void QGLContext::setValid( bool valid )
+ \internal
+
+ Forces the GL rendering context to be valid.
+*/
+
+/*!
+ \fn bool QGLContext::isSharing() const
+
+ Returns TRUE if display list sharing with another context was
+ requested in the create() call and the GL system was able to
+ fulfill this request; otherwise returns FALSE. Note that display
+ list sharing might not be supported between contexts with
+ different formats.
+*/
+
+/*!
+ \fn bool QGLContext::deviceIsPixmap() const
+
+ Returns TRUE if the paint device of this context is a pixmap;
+ otherwise returns FALSE.
+*/
+
+/*!
+ \fn bool QGLContext::windowCreated() const
+
+ Returns TRUE if a window has been created for this context;
+ otherwise returns FALSE.
+
+ \sa setWindowCreated()
+*/
+
+/*!
+ \fn void QGLContext::setWindowCreated( bool on )
+
+ If \a on is TRUE the context has had a window created for it. If
+ \a on is FALSE no window has been created for the context.
+
+ \sa windowCreated()
+*/
+
+/*!
+ \fn uint QGLContext::colorIndex( const QColor& c ) const
+
+ \internal
+
+ Returns a colormap index for the color c, in ColorIndex mode. Used
+ by qglColor() and qglClearColor().
+*/
+
+
+/*!
+ \fn bool QGLContext::initialized() const
+
+ Returns TRUE if this context has been initialized, i.e. if
+ QGLWidget::initializeGL() has been performed on it; otherwise
+ returns FALSE.
+
+ \sa setInitialized()
+*/
+
+/*!
+ \fn void QGLContext::setInitialized( bool on )
+
+ If \a on is TRUE the context has been initialized, i.e.
+ QGLContext::setInitialized() has been called on it. If \a on is
+ FALSE the context has not been initialized.
+
+ \sa initialized()
+*/
+
+/*!
+ \fn const QGLContext* QGLContext::currentContext()
+
+ Returns the current context, i.e. the context to which any OpenGL
+ commands will currently be directed. Returns 0 if no context is
+ current.
+
+ \sa makeCurrent()
+*/
+
+/*!
+ \fn QColor QGLContext::overlayTransparentColor() const
+
+ If this context is a valid context in an overlay plane, returns
+ the plane's transparent color. Otherwise returns an \link
+ QColor::isValid() invalid \endlink color.
+
+ The returned color's \link QColor::pixel() pixel \endlink value is
+ the index of the transparent color in the colormap of the overlay
+ plane. (Naturally, the color's RGB values are meaningless.)
+
+ The returned QColor object will generally work as expected only
+ when passed as the argument to QGLWidget::qglColor() or
+ QGLWidget::qglClearColor(). Under certain circumstances it can
+ also be used to draw transparent graphics with a QPainter. See the
+ examples/opengl/overlay_x11 example for details.
+*/
+
+
+/*!
+ Creates the GL context. Returns TRUE if it was successful in
+ creating a valid GL rendering context on the paint device
+ specified in the constructor; otherwise returns FALSE (i.e. the
+ context is invalid).
+
+ After successful creation, format() returns the set of features of
+ the created GL rendering context.
+
+ If \a shareContext points to a valid QGLContext, this method will
+ try to establish OpenGL display list sharing between this context
+ and the \a shareContext. Note that this may fail if the two
+ contexts have different formats. Use isSharing() to see if sharing
+ succeeded.
+
+ \warning Implementation note: initialization of C++ class
+ members usually takes place in the class constructor. QGLContext
+ is an exception because it must be simple to customize. The
+ virtual functions chooseContext() (and chooseVisual() for X11) can
+ be reimplemented in a subclass to select a particular context. The
+ problem is that virtual functions are not properly called during
+ construction (even though this is correct C++) because C++
+ constructs class hierarchies from the bottom up. For this reason
+ we need a create() function.
+
+ \sa chooseContext(), format(), isValid()
+*/
+
+bool QGLContext::create( const QGLContext* shareContext )
+{
+ reset();
+ d->valid = chooseContext( shareContext );
+ return d->valid;
+}
+
+
+
+/*!
+ \fn bool QGLContext::chooseContext( const QGLContext* shareContext = 0 )
+
+ This semi-internal function is called by create(). It creates a
+ system-dependent OpenGL handle that matches the format() of \a
+ shareContext as closely as possible.
+
+ On Windows, it calls the virtual function choosePixelFormat(),
+ which finds a matching pixel format identifier. On X11, it calls
+ the virtual function chooseVisual() which finds an appropriate X
+ visual. On other platforms it may work differently.
+*/
+
+
+/*!
+ \fn void QGLContext::reset()
+
+ Resets the context and makes it invalid.
+
+ \sa create(), isValid()
+*/
+
+
+/*!
+ \fn void QGLContext::makeCurrent()
+
+ Makes this context the current OpenGL rendering context. All GL
+ functions you call operate on this context until another context
+ is made current.
+
+ In some very rare cases the underlying call may fail. If this
+ occurs an error message is output to stderr.
+*/
+
+
+/*!
+ \fn void QGLContext::swapBuffers() const
+
+ Swaps the screen contents with an off-screen buffer. Only works if
+ the context is in double buffer mode.
+
+ \sa QGLFormat::setDoubleBuffer()
+*/
+
+
+/*!
+ \fn void QGLContext::doneCurrent()
+
+ Makes no GL context the current context. Normally, you do not need
+ to call this function; QGLContext calls it as necessary.
+*/
+
+
+/*!
+ \fn QPaintDevice* QGLContext::device() const
+
+ Returns the paint device set for this context.
+
+ \sa QGLContext::QGLContext()
+*/
+
+/*!
+ \fn void QGLContext::generateFontDisplayLists( const QFont& font, int listBase )
+
+ Generates a set of 256 display lists for the 256 first characters
+ in the font \a font. The first list will start at index \a listBase.
+
+ \sa QGLWidget::renderText()
+*/
+
+
+/*****************************************************************************
+ QGLWidget implementation
+ *****************************************************************************/
+
+
+/*!
+ \class QGLWidget qgl.h
+ \brief The QGLWidget class is a widget for rendering OpenGL graphics.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \ingroup graphics
+ \ingroup images
+ \mainclass
+ \module OpenGL
+
+ QGLWidget provides functionality for displaying OpenGL<sup>*</sup>
+ graphics integrated into a Qt application. It is very simple to
+ use. You inherit from it and use the subclass like any other
+ QWidget, except that instead of drawing the widget's contents
+ using QPainter etc. you use the standard OpenGL rendering
+ commands.
+
+ QGLWidget provides three convenient virtual functions that you can
+ reimplement in your subclass to perform the typical OpenGL tasks:
+
+ \list
+ \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget
+ needs to be updated.
+ \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
+ called whenever the the widget has been resized (and also when it
+ is shown for the first time because all newly created widgets get a
+ resize event automatically).
+ \i initializeGL() - Sets up the OpenGL rendering context, defines display
+ lists, etc. Gets called once before the first time resizeGL() or
+ paintGL() is called.
+ \endlist
+
+ Here is a rough outline of how a QGLWidget subclass might look:
+
+ \code
+ class MyGLDrawer : public QGLWidget
+ {
+ Q_OBJECT // must include this if you use Qt signals/slots
+
+ public:
+ MyGLDrawer( QWidget *parent, const char *name )
+ : QGLWidget(parent, name) {}
+
+ protected:
+
+ void initializeGL()
+ {
+ // Set up the rendering context, define display lists etc.:
+ ...
+ glClearColor( 0.0, 0.0, 0.0, 0.0 );
+ glEnable(GL_DEPTH_TEST);
+ ...
+ }
+
+ void resizeGL( int w, int h )
+ {
+ // setup viewport, projection etc.:
+ glViewport( 0, 0, (GLint)w, (GLint)h );
+ ...
+ glFrustum( ... );
+ ...
+ }
+
+ void paintGL()
+ {
+ // draw the scene:
+ ...
+ glRotatef( ... );
+ glMaterialfv( ... );
+ glBegin( GL_QUADS );
+ glVertex3f( ... );
+ glVertex3f( ... );
+ ...
+ glEnd();
+ ...
+ }
+
+ };
+ \endcode
+
+ If you need to trigger a repaint from places other than paintGL()
+ (a typical example is when using \link QTimer timers\endlink to
+ animate scenes), you should call the widget's updateGL() function.
+
+ Your widget's OpenGL rendering context is made current when
+ paintGL(), resizeGL(), or initializeGL() is called. If you need to
+ call the standard OpenGL API functions from other places (e.g. in
+ your widget's constructor or in your own paint functions), you
+ must call makeCurrent() first.
+
+ QGLWidget provides functions for requesting a new display \link
+ QGLFormat format\endlink and you can also create widgets with
+ customized rendering \link QGLContext contexts\endlink.
+
+ You can also share OpenGL display lists between QGLWidgets (see
+ the documentation of the QGLWidget constructors for details).
+
+ \section1 Overlays
+
+ The QGLWidget creates a GL overlay context in addition to the
+ normal context if overlays are supported by the underlying system.
+
+ If you want to use overlays, you specify it in the \link QGLFormat
+ format\endlink. (Note: Overlay must be requested in the format
+ passed to the QGLWidget constructor.) Your GL widget should also
+ implement some or all of these virtual methods:
+
+ \list
+ \i paintOverlayGL()
+ \i resizeOverlayGL()
+ \i initializeOverlayGL()
+ \endlist
+
+ These methods work in the same way as the normal paintGL() etc.
+ functions, except that they will be called when the overlay
+ context is made current. You can explicitly make the overlay
+ context current by using makeOverlayCurrent(), and you can access
+ the overlay context directly (e.g. to ask for its transparent
+ color) by calling overlayContext().
+
+ On X servers in which the default visual is in an overlay plane,
+ non-GL Qt windows can also be used for overlays. See the
+ examples/opengl/overlay_x11 example program for details.
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+*/
+
+// ### BCI - fix in 4.0
+
+// the display list cache can't be global because display lists are
+// tied to the GL contexts for each individual widget
+
+class QGLWidgetPrivate
+{
+public:
+ QMap<QString, int> displayListCache;
+};
+
+static QPtrDict<QGLWidgetPrivate> * qgl_d_ptr = 0;
+static QSingleCleanupHandler< QPtrDict<QGLWidgetPrivate> > qgl_cleanup_d_ptr;
+
+static QGLWidgetPrivate * qgl_d( const QGLWidget * w )
+{
+ if ( !qgl_d_ptr ) {
+ qgl_d_ptr = new QPtrDict<QGLWidgetPrivate>;
+ qgl_cleanup_d_ptr.set( &qgl_d_ptr );
+ qgl_d_ptr->setAutoDelete( TRUE );
+ }
+ QGLWidgetPrivate * ret = qgl_d_ptr->find( (void *) w );
+ if ( !ret ) {
+ ret = new QGLWidgetPrivate;
+ qgl_d_ptr->replace( (void *) w, ret );
+ }
+ return ret;
+}
+
+void qgl_delete_d( const QGLWidget * w )
+{
+ if ( qgl_d_ptr )
+ qgl_d_ptr->remove( (void *) w );
+}
+
+/*!
+ Constructs an OpenGL widget with a \a parent widget and a \a name.
+
+ The \link QGLFormat::defaultFormat() default format\endlink is
+ used. The widget will be \link isValid() invalid\endlink if the
+ system has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the QWidget constructor.
+
+ If the \a shareWidget parameter points to a valid QGLWidget, this
+ widget will share OpenGL display lists with \a shareWidget. If
+ this widget and \a shareWidget have different \link format()
+ formats\endlink, display list sharing may fail. You can check
+ whether display list sharing succeeded by calling isSharing().
+
+ The initialization of OpenGL rendering state, etc. should be done
+ by overriding the initializeGL() function, rather than in the
+ constructor of your QGLWidget subclass.
+
+ \sa QGLFormat::defaultFormat()
+*/
+
+QGLWidget::QGLWidget( QWidget *parent, const char *name,
+ const QGLWidget* shareWidget, WFlags f )
+ : QWidget( parent, name, f | Qt::WWinOwnDC | Qt::WNoAutoErase )
+{
+ init( new QGLContext(QGLFormat::defaultFormat(), this), shareWidget );
+}
+
+
+/*!
+ Constructs an OpenGL widget with parent \a parent, called \a name.
+
+ The \a format argument specifies the desired \link QGLFormat
+ rendering options \endlink. If the underlying OpenGL/Window system
+ cannot satisfy all the features requested in \a format, the
+ nearest subset of features will be used. After creation, the
+ format() method will return the actual format obtained.
+
+ The widget will be \link isValid() invalid\endlink if the system
+ has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the QWidget constructor.
+
+ If the \a shareWidget parameter points to a valid QGLWidget, this
+ widget will share OpenGL display lists with \a shareWidget. If
+ this widget and \a shareWidget have different \link format()
+ formats\endlink, display list sharing may fail. You can check
+ whether display list sharing succeeded by calling isSharing().
+
+ The initialization of OpenGL rendering state, etc. should be done
+ by overriding the initializeGL() function, rather than in the
+ constructor of your QGLWidget subclass.
+
+ \sa QGLFormat::defaultFormat(), isValid()
+*/
+
+QGLWidget::QGLWidget( const QGLFormat &format, QWidget *parent,
+ const char *name, const QGLWidget* shareWidget,
+ WFlags f )
+ : QWidget( parent, name, f | Qt::WWinOwnDC | Qt::WNoAutoErase )
+{
+ init( new QGLContext(format, this), shareWidget );
+}
+
+/*!
+ Constructs an OpenGL widget with parent \a parent, called \a name.
+
+ The \a context argument is a pointer to the QGLContext that
+ you wish to be bound to this widget. This allows you to pass in
+ your own QGLContext sub-classes.
+
+ The widget will be \link isValid() invalid\endlink if the system
+ has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the QWidget constructor.
+
+ If the \a shareWidget parameter points to a valid QGLWidget, this
+ widget will share OpenGL display lists with \a shareWidget. If
+ this widget and \a shareWidget have different \link format()
+ formats\endlink, display list sharing may fail. You can check
+ whether display list sharing succeeded by calling isSharing().
+
+ The initialization of OpenGL rendering state, etc. should be done
+ by overriding the initializeGL() function, rather than in the
+ constructor of your QGLWidget subclass.
+
+ \sa QGLFormat::defaultFormat(), isValid()
+*/
+QGLWidget::QGLWidget( QGLContext *context, QWidget *parent,
+ const char *name, const QGLWidget *shareWidget, WFlags f )
+ : QWidget( parent, name, f | Qt::WWinOwnDC | Qt::WNoAutoErase )
+{
+ init( context, shareWidget );
+}
+
+/*!
+ Destroys the widget.
+*/
+
+QGLWidget::~QGLWidget()
+{
+#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
+ bool doRelease = ( glcx && glcx->windowCreated() );
+#endif
+ qgl_delete_d( this );
+ delete glcx;
+#if defined(Q_WGL)
+ delete olcx;
+#endif
+#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
+ if ( doRelease )
+ glXReleaseBuffersMESA( x11Display(), winId() );
+#endif
+#if defined(Q_WS_MAC)
+ if(gl_pix) {
+ delete gl_pix;
+ gl_pix = NULL;
+ }
+#endif
+ cleanupColormaps();
+}
+
+
+
+
+
+/*!
+ \fn QGLFormat QGLWidget::format() const
+
+ Returns the format of the contained GL rendering context.
+*/
+
+/*!
+ \fn bool QGLWidget::doubleBuffer() const
+
+ Returns TRUE if the contained GL rendering context has double
+ buffering; otherwise returns FALSE.
+
+ \sa QGLFormat::doubleBuffer()
+*/
+
+/*!
+ \fn void QGLWidget::setAutoBufferSwap( bool on )
+
+ If \a on is TRUE automatic GL buffer swapping is switched on;
+ otherwise it is switched off.
+
+ If \a on is TRUE and the widget is using a double-buffered format,
+ the background and foreground GL buffers will automatically be
+ swapped after each paintGL() call.
+
+ The buffer auto-swapping is on by default.
+
+ \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
+*/
+
+/*!
+ \fn bool QGLWidget::autoBufferSwap() const
+
+ Returns TRUE if the widget is doing automatic GL buffer swapping;
+ otherwise returns FALSE.
+
+ \sa setAutoBufferSwap()
+*/
+
+/*!
+ \fn bool QGLWidget::isValid() const
+
+ Returns TRUE if the widget has a valid GL rendering context;
+ otherwise returns FALSE. A widget will be invalid if the system
+ has no \link QGLFormat::hasOpenGL() OpenGL support\endlink.
+*/
+
+bool QGLWidget::isValid() const
+{
+ return glcx->isValid();
+}
+
+/*!
+ \fn bool QGLWidget::isSharing() const
+
+ Returns TRUE if display list sharing with another QGLWidget was
+ requested in the constructor, and the GL system was able to
+ provide it; otherwise returns FALSE. The GL system may fail to
+ provide display list sharing if the two QGLWidgets use different
+ formats.
+
+ \sa format()
+*/
+
+bool QGLWidget::isSharing() const
+{
+ return glcx->isSharing();
+}
+
+/*!
+ \fn void QGLWidget::makeCurrent()
+
+ Makes this widget the current widget for OpenGL operations, i.e.
+ makes the widget's rendering context the current OpenGL rendering
+ context.
+*/
+
+void QGLWidget::makeCurrent()
+{
+#if defined( Q_WS_MAC )
+ macInternalDoubleBuffer(); //make sure the correct context is used
+#endif
+ glcx->makeCurrent();
+}
+
+/*!
+ \fn void QGLWidget::doneCurrent()
+
+ Makes no GL context the current context. Normally, you do not need
+ to call this function; QGLContext calls it as necessary. However,
+ it may be useful in multithreaded environments.
+*/
+
+void QGLWidget::doneCurrent()
+{
+ glcx->doneCurrent();
+}
+
+/*!
+ \fn void QGLWidget::swapBuffers()
+
+ Swaps the screen contents with an off-screen buffer. This only
+ works if the widget's format specifies double buffer mode.
+
+ Normally, there is no need to explicitly call this function
+ because it is done automatically after each widget repaint, i.e.
+ each time after paintGL() has been executed.
+
+ \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
+*/
+
+void QGLWidget::swapBuffers()
+{
+ glcx->swapBuffers();
+#if defined(Q_WS_MAC)
+ if(macInternalDoubleBuffer() && gl_pix)
+ bitBlt(this, 0, 0, gl_pix);
+#endif
+}
+
+
+/*!
+ \fn const QGLContext* QGLWidget::overlayContext() const
+
+ Returns the overlay context of this widget, or 0 if this widget
+ has no overlay.
+
+ \sa context()
+*/
+
+
+
+/*!
+ \fn void QGLWidget::makeOverlayCurrent()
+
+ Makes the overlay context of this widget current. Use this if you
+ need to issue OpenGL commands to the overlay context outside of
+ initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
+
+ Does nothing if this widget has no overlay.
+
+ \sa makeCurrent()
+*/
+
+
+/*
+ \obsolete
+
+ Sets a new format for this widget.
+
+ If the underlying OpenGL/Window system cannot satisfy all the
+ features requested in \a format, the nearest subset of features will
+ be used. After creation, the format() method will return the actual
+ rendering context format obtained.
+
+ The widget will be assigned a new QGLContext, and the initializeGL()
+ function will be executed for this new context before the first
+ resizeGL() or paintGL().
+
+ This method will try to keep any existing display list sharing with
+ other QGLWidgets, but it may fail. Use isSharing() to test.
+
+ \sa format(), isSharing(), isValid()
+*/
+
+void QGLWidget::setFormat( const QGLFormat &format )
+{
+ setContext( new QGLContext(format,this) );
+}
+
+
+
+
+/*!
+ \fn const QGLContext *QGLWidget::context() const
+
+ Returns the context of this widget.
+
+ It is possible that the context is not valid (see isValid()), for
+ example, if the underlying hardware does not support the format
+ attributes that were requested.
+*/
+
+/*
+ \obsolete
+
+ \fn void QGLWidget::setContext( QGLContext *context,
+ const QGLContext* shareContext,
+ bool deleteOldContext )
+
+ Sets a new context for this widget. The QGLContext \a context must
+ be created using \e new. QGLWidget will delete \a context when
+ another context is set or when the widget is destroyed.
+
+ If \a context is invalid, QGLContext::create() is performed on
+ it. The initializeGL() function will then be executed for the new
+ context before the first resizeGL() or paintGL().
+
+ If \a context is invalid, this method will try to keep any existing
+ display list sharing with other QGLWidgets this widget currently
+ has, or (if \a shareContext points to a valid context) start display
+ list sharing with that context, but it may fail. Use isSharing() to
+ test.
+
+ If \a deleteOldContext is TRUE (the default), the existing context
+ will be deleted. You may use FALSE here if you have kept a pointer
+ to the old context (as returned by context()), and want to restore
+ that context later.
+
+ \sa context(), isSharing()
+*/
+
+
+
+/*!
+ \fn void QGLWidget::updateGL()
+
+ Updates the widget by calling glDraw().
+*/
+
+void QGLWidget::updateGL()
+{
+ glDraw();
+}
+
+
+/*!
+ \fn void QGLWidget::updateOverlayGL()
+
+ Updates the widget's overlay (if any). Will cause the virtual
+ function paintOverlayGL() to be executed.
+
+ The widget's rendering context will become the current context and
+ initializeGL() will be called if it hasn't already been called.
+*/
+
+
+/*!
+ This virtual function is called once before the first call to
+ paintGL() or resizeGL(), and then once whenever the widget has
+ been assigned a new QGLContext. Reimplement it in a subclass.
+
+ This function should set up any required OpenGL context rendering
+ flags, defining display lists, etc.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+*/
+
+void QGLWidget::initializeGL()
+{
+}
+
+
+/*!
+ This virtual function is called whenever the widget needs to be
+ painted. Reimplement it in a subclass.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+*/
+
+void QGLWidget::paintGL()
+{
+}
+
+
+/*!
+ \fn void QGLWidget::resizeGL( int width , int height )
+
+ This virtual function is called whenever the widget has been
+ resized. The new size is passed in \a width and \a height.
+ Reimplement it in a subclass.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+*/
+
+void QGLWidget::resizeGL( int, int )
+{
+}
+
+
+
+/*!
+ This virtual function is used in the same manner as initializeGL()
+ except that it operates on the widget's overlay context instead of
+ the widget's main context. This means that initializeOverlayGL()
+ is called once before the first call to paintOverlayGL() or
+ resizeOverlayGL(). Reimplement it in a subclass.
+
+ This function should set up any required OpenGL context rendering
+ flags, defining display lists, etc. for the overlay context.
+
+ There is no need to call makeOverlayCurrent() because this has
+ already been done when this function is called.
+*/
+
+void QGLWidget::initializeOverlayGL()
+{
+}
+
+
+/*!
+ This virtual function is used in the same manner as paintGL()
+ except that it operates on the widget's overlay context instead of
+ the widget's main context. This means that paintOverlayGL() is
+ called whenever the widget's overlay needs to be painted.
+ Reimplement it in a subclass.
+
+ There is no need to call makeOverlayCurrent() because this has
+ already been done when this function is called.
+*/
+
+void QGLWidget::paintOverlayGL()
+{
+}
+
+
+/*!
+ \fn void QGLWidget::resizeOverlayGL( int width , int height )
+
+ This virtual function is used in the same manner as paintGL()
+ except that it operates on the widget's overlay context instead of
+ the widget's main context. This means that resizeOverlayGL() is
+ called whenever the widget has been resized. The new size is
+ passed in \a width and \a height. Reimplement it in a subclass.
+
+ There is no need to call makeOverlayCurrent() because this has
+ already been done when this function is called.
+*/
+
+void QGLWidget::resizeOverlayGL( int, int )
+{
+}
+
+
+
+
+/*!
+ Handles paint events. Will cause the virtual paintGL() function to
+ be called.
+
+ The widget's rendering context will become the current context and
+ initializeGL() will be called if it hasn't already been called.
+*/
+
+void QGLWidget::paintEvent( QPaintEvent * )
+{
+ glDraw();
+ updateOverlayGL();
+}
+
+
+/*!
+ \fn void QGLWidget::resizeEvent( QResizeEvent * )
+
+ Handles resize events. Calls the virtual function resizeGL().
+*/
+
+
+/*!
+ \fn void QGLWidget::setMouseTracking( bool enable )
+
+ \reimp
+*/
+
+
+/*!
+ Renders the current scene on a pixmap and returns the pixmap.
+
+ You can use this method on both visible and invisible QGLWidgets.
+
+ This method will create a pixmap and a temporary QGLContext to
+ render on the pixmap. It will then call initializeGL(),
+ resizeGL(), and paintGL() on this context. Finally, the widget's
+ original GL context is restored.
+
+ The size of the pixmap will be \a w pixels wide and \a h pixels
+ high unless one of these parameters is 0 (the default), in which
+ case the pixmap will have the same size as the widget.
+
+ If \a useContext is TRUE, this method will try to be more
+ efficient by using the existing GL context to render the pixmap.
+ The default is FALSE. Only use TRUE if you understand the risks.
+
+ Overlays are not rendered onto the pixmap.
+
+ If the GL rendering context and the desktop have different bit
+ depths, the result will most likely look surprising.
+
+ Note that the creation of display lists, modifications of the view
+ frustum etc. should be done from within initializeGL(). If this is
+ not done, the temporary QGLContext will not be initialized
+ properly, and the rendered pixmap may be incomplete/corrupted.
+*/
+
+QPixmap QGLWidget::renderPixmap( int w, int h, bool useContext )
+{
+ QSize sz = size();
+ if ( (w > 0) && (h > 0) )
+ sz = QSize( w, h );
+
+#if defined(Q_WS_X11)
+ QPixmap pm( sz.width(), sz.height(), x11Depth() );
+ bool needConversion = x11Visual() != QPaintDevice::x11AppVisual();
+
+ // make sure the pixmap uses the same visual as the widget itself
+ if ( needConversion ) {
+ QPaintDeviceX11Data* xd = pm.getX11Data( TRUE );
+ xd->x_depth = x11Depth();
+ xd->x_visual = (Visual *) x11Visual();
+ pm.setX11Data( xd );
+ }
+#else
+ QPixmap pm;
+ pm.resize( sz );
+#endif
+
+ glcx->doneCurrent();
+
+ bool success = TRUE;
+
+ if ( useContext && isValid() && renderCxPm( &pm ) )
+ return pm;
+
+ QGLFormat fmt = glcx->requestedFormat();
+ fmt.setDirectRendering( FALSE ); // Direct is unlikely to work
+ fmt.setDoubleBuffer( FALSE ); // We don't need dbl buf
+
+ QGLContext* ocx = glcx;
+ bool wasCurrent = (QGLContext::currentContext() == ocx );
+ ocx->doneCurrent();
+ glcx = new QGLContext( fmt, &pm );
+ glcx->create();
+
+ if ( glcx->isValid() )
+ updateGL();
+ else
+ success = FALSE;
+
+ delete glcx;
+ glcx = ocx;
+
+ if ( wasCurrent )
+ ocx->makeCurrent();
+
+ if ( success ) {
+#if defined(Q_WS_X11)
+ if ( needConversion ) {
+ QImage image = pm.convertToImage();
+ QPixmap p;
+ p = image;
+ return p;
+ }
+#endif
+ return pm;
+ } else
+ return QPixmap();
+}
+
+
+
+/*!
+ Returns an image of the frame buffer. If \a withAlpha is TRUE the
+ alpha channel is included.
+
+ Depending on your hardware, you can explicitly select which color
+ buffer to grab with a glReadBuffer() call before calling this
+ function.
+*/
+QImage QGLWidget::grabFrameBuffer( bool withAlpha )
+{
+#if defined( Q_WS_MAC )
+ if(dblbuf == macInternalDoubleBuffer(FALSE) && gl_pix) //why not optimize?
+ return ((QPixmap*)gl_pix)->convertToImage();
+#endif
+ makeCurrent();
+ QImage res;
+ int w = width();
+ int h = height();
+ if ( format().rgba() ) {
+ res = QImage( w, h, 32 );
+ glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, res.bits() );
+ if ( QImage::systemByteOrder() == QImage::BigEndian ) {
+ // OpenGL gives RGBA; Qt wants ARGB
+ uint *p = (uint*)res.bits();
+ uint *end = p + w*h;
+ if ( withAlpha && format().alpha() ) {
+ while ( p < end ) {
+ uint a = *p << 24;
+ *p = (*p >> 8) | a;
+ p++;
+ }
+ }
+ else {
+ while ( p < end )
+ *p++ >>= 8;
+ }
+ }
+ else {
+ // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
+ res = res.swapRGB();
+ }
+ res.setAlphaBuffer( withAlpha && format().alpha() );
+ }
+ else {
+#if defined (Q_WS_WIN)
+ res = QImage( w, h, 8 );
+ glReadPixels( 0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
+ res.bits() );
+ int palSize = 0;
+ const QRgb* pal = QColor::palette( &palSize );
+ if ( pal && palSize ) {
+ res.setNumColors( palSize );
+ for ( int i = 0; i < palSize; i++ )
+ res.setColor( i, pal[i] );
+ }
+#endif
+ }
+
+ return res.mirror();
+}
+
+
+
+/*!
+ Initializes OpenGL for this widget's context. Calls the virtual
+ function initializeGL().
+*/
+
+void QGLWidget::glInit()
+{
+ if ( !isValid() )
+ return;
+ makeCurrent();
+ initializeGL();
+ glcx->setInitialized( TRUE );
+}
+
+
+/*!
+ Executes the virtual function paintGL().
+
+ The widget's rendering context will become the current context and
+ initializeGL() will be called if it hasn't already been called.
+*/
+
+void QGLWidget::glDraw()
+{
+ if ( !isValid() )
+ return;
+ makeCurrent();
+ if ( glcx->deviceIsPixmap() )
+ glDrawBuffer( GL_FRONT );
+ if ( !glcx->initialized() ) {
+ glInit();
+ QPaintDeviceMetrics dm( glcx->device() );
+ resizeGL( dm.width(), dm.height() ); // New context needs this "resize"
+ }
+ paintGL();
+ if ( doubleBuffer() ) {
+ if ( autoSwap )
+ swapBuffers();
+ } else {
+ glFlush();
+#if defined( Q_WS_MAC )
+ if(dblbuf && gl_pix)
+ bitBlt(this, 0, 0, gl_pix);
+#endif
+ }
+}
+
+
+/*!
+ Convenience function for specifying a drawing color to OpenGL.
+ Calls glColor3 (in RGBA mode) or glIndex (in color-index mode)
+ with the color \a c. Applies to the current GL context.
+
+ \sa qglClearColor(), QGLContext::currentContext(), QColor
+*/
+
+void QGLWidget::qglColor( const QColor& c ) const
+{
+ const QGLContext* ctx = QGLContext::currentContext();
+ if ( ctx ) {
+ if ( ctx->format().rgba() )
+ glColor3ub( c.red(), c.green(), c.blue() );
+
+ else if ( ctx->device() == context()->device()
+ && !cmap.isEmpty() ) { // QGLColormap in use?
+ int i = cmap.find( c.rgb() );
+ if ( i < 0 )
+ i = cmap.findNearest( c.rgb() );
+ glIndexi( i );
+ } else
+ glIndexi( ctx->colorIndex( c ) );
+ }
+}
+
+/*!
+ Convenience function for specifying the clearing color to OpenGL.
+ Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
+ mode) with the color \a c. Applies to the current GL context.
+
+ \sa qglColor(), QGLContext::currentContext(), QColor
+*/
+
+void QGLWidget::qglClearColor( const QColor& c ) const
+{
+ const QGLContext* ctx = QGLContext::currentContext();
+ if ( ctx ) {
+ if ( ctx->format().rgba() )
+ glClearColor( (GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0,
+ (GLfloat)c.blue() / 255.0, (GLfloat) 0.0 );
+ else if ( ctx->device() == context()->device()
+ && !cmap.isEmpty() ) { // QGLColormap in use?
+ int i = cmap.find( c.rgb() );
+ if ( i < 0 )
+ i = cmap.findNearest( c.rgb() );
+ glClearIndex( i );
+ } else
+ glClearIndex( ctx->colorIndex( c ) );
+ }
+}
+
+
+/*!
+ Converts the image \a img into the unnamed format expected by
+ OpenGL functions such as glTexImage2D(). The returned image is not
+ usable as a QImage, but QImage::width(), QImage::height() and
+ QImage::bits() may be used with OpenGL. The following few lines
+ are from the texture example. Most of the code is irrelevant, so
+ we just quote the relevant bits:
+
+ \quotefile opengl/texture/gltexobj.cpp
+ \skipto tex1
+ \printline tex1
+ \printline gllogo.bmp
+
+ We create \e tex1 (and another variable) for OpenGL, and load a real
+ image into \e buf.
+
+ \skipto convertToGLFormat
+ \printline convertToGLFormat
+
+ A few lines later, we convert \e buf into OpenGL format and store it
+ in \e tex1.
+
+ \skipto glTexImage2D
+ \printline glTexImage2D
+ \printline tex1.bits
+
+ Note the dimension restrictions for texture images as described in
+ the glTexImage2D() documentation. The width must be 2^m + 2*border
+ and the height 2^n + 2*border where m and n are integers and
+ border is either 0 or 1.
+
+ Another function in the same example uses \e tex1 with OpenGL.
+*/
+
+
+QImage QGLWidget::convertToGLFormat( const QImage& img )
+{
+ QImage res = img.convertDepth( 32 );
+ res = res.mirror();
+
+ if ( QImage::systemByteOrder() == QImage::BigEndian ) {
+ // Qt has ARGB; OpenGL wants RGBA
+ for ( int i=0; i < res.height(); i++ ) {
+ uint *p = (uint*)res.scanLine( i );
+ uint *end = p + res.width();
+ while ( p < end ) {
+ *p = (*p << 8) | ((*p >> 24) & 0xFF);
+ p++;
+ }
+ }
+ }
+ else {
+ // Qt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards)
+ res = res.swapRGB();
+ }
+ return res;
+}
+
+
+/*!
+ \fn QGLColormap & QGLWidget::colormap() const
+
+ Returns the colormap for this widget.
+
+ Usually it is only top-level widgets that can have different
+ colormaps installed. Asking for the colormap of a child widget
+ will return the colormap for the child's top-level widget.
+
+ If no colormap has been set for this widget, the QColormap
+ returned will be empty.
+
+ \sa setColormap()
+*/
+
+/*!
+ \fn void QGLWidget::setColormap( const QGLColormap & cmap )
+
+ Set the colormap for this widget to \a cmap. Usually it is only
+ top-level widgets that can have colormaps installed.
+
+ \sa colormap()
+*/
+
+int QGLWidget::displayListBase( const QFont & fnt, int listBase )
+{
+ int base;
+
+ QGLWidgetPrivate * d = qgl_d( this );
+ if ( !d || !glcx ) { // this can't happen unless we run out of mem
+ return 0;
+ }
+
+ // always regenerate font disp. lists for pixmaps - hw accelerated
+ // contexts can't handle this otherwise
+ bool regenerate = glcx->deviceIsPixmap();
+
+#if 0 // QT_NO_XFTFREETYPE
+ // font color needs to be part of the font cache key when using
+ // antialiased fonts since one set of glyphs needs to be generated
+ // for each font color
+ QString color_key;
+ if (fnt.styleStrategy() != QFont::NoAntialias) {
+ GLfloat color[4];
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
+ }
+ QString key = fnt.key() + color_key + QString::number((int) regenerate);
+#else
+ QString key = fnt.key() + QString::number((int) regenerate);
+#endif
+
+ if ( !regenerate && (d->displayListCache.find( key ) != d->displayListCache.end()) ) {
+ base = d->displayListCache[ key ];
+ } else {
+ int maxBase = listBase - 256;
+ QMapConstIterator<QString,int> it;
+ for ( it = d->displayListCache.begin(); it != d->displayListCache.end(); ++it ) {
+ if ( maxBase < it.data() ) {
+ maxBase = it.data();
+ }
+ }
+ maxBase += 256;
+ glcx->generateFontDisplayLists( fnt, maxBase );
+ d->displayListCache[ key ] = maxBase;
+ base = maxBase;
+ }
+ return base;
+}
+
+/*!
+ Renders the string \a str into the GL context of this widget.
+
+ \a x and \a y are specified in window coordinates, with the origin
+ in the upper left-hand corner of the window. If \a fnt is not
+ specified, the currently set application font will be used to
+ render the string. To change the color of the rendered text you can
+ use the glColor() call (or the qglColor() convenience function),
+ just before the renderText() call. Note that if you have
+ GL_LIGHTING enabled, the string will not appear in the color you
+ want. You should therefore switch lighting off before using
+ renderText().
+
+ \a listBase specifies the index of the first display list that is
+ generated by this function. The default value is 2000. 256 display
+ lists will be generated, one for each of the first 256 characters
+ in the font that is used to render the string. If several fonts are
+ used in the same widget, the display lists for these fonts will
+ follow the last generated list. You would normally not have to
+ change this value unless you are using lists in the same range. The
+ lists are deleted when the widget is destroyed.
+
+ Note: This function only works reliably with ASCII strings.
+*/
+
+void QGLWidget::renderText( int x, int y, const QString & str, const QFont & fnt, int listBase )
+{
+ if (str.isEmpty())
+ return;
+ makeCurrent();
+ glPushAttrib( GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_LIST_BIT | GL_CURRENT_BIT );
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho( 0, width(), height(), 0, -1, 1 );
+ glMatrixMode( GL_MODELVIEW );
+ glPushMatrix();
+ glLoadIdentity();
+
+ glRasterPos2i( 0, 0 );
+ glBitmap(0, 0, 0, 0, x, -y, NULL);
+ glListBase( displayListBase( fnt, listBase ) );
+ const char *cstr = str.latin1();
+ glCallLists( qstrlen(cstr), GL_UNSIGNED_BYTE, cstr );
+
+ // restore the matrix stacks and GL state
+ glPopMatrix();
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix();
+ glPopAttrib();
+}
+
+/*! \overload
+
+ \a x, \a y and \a z are specified in scene or object coordinates
+ relative to the currently set projection and model matrices. This
+ can be useful if you want to annotate models with text labels and
+ have the labels move with the model as it is rotated etc.
+*/
+void QGLWidget::renderText( double x, double y, double z, const QString & str, const QFont & fnt,
+ int listBase )
+{
+ if (str.isEmpty())
+ return;
+ makeCurrent();
+ glRasterPos3d( x, y, z );
+ glPushAttrib( GL_LIST_BIT );
+ glListBase( displayListBase( fnt, listBase ) );
+ const char *cstr = str.latin1();
+ glCallLists( qstrlen(cstr), GL_UNSIGNED_BYTE, cstr );
+ glPopAttrib();
+}
+
+/*****************************************************************************
+ QGL classes overview documentation.
+ *****************************************************************************/
+
+/*!
+
+\page opengl.html
+
+\title Qt OpenGL 3D Graphics
+
+\if defined(commercial)
+This module is part of the \link commercialeditions.html Qt Enterprise
+Edition\endlink.
+\endif
+
+\section1 Introduction
+
+OpenGL is a standard API for rendering 3D graphics.
+
+OpenGL only deals with 3D rendering and provides little or no support
+for GUI programming issues. The user interface for an
+OpenGL<sup>*</sup> application must be created with another toolkit,
+such as Motif on the X platform, Microsoft Foundation Classes (MFC)
+under Windows, or Qt on \e both platforms.
+
+The Qt OpenGL module makes it easy to use OpenGL in Qt applications.
+It provides an OpenGL widget class that can be used just like any
+other Qt widget, except that it opens an OpenGL display buffer where
+you can use the OpenGL API to render the contents.
+
+The Qt OpenGL module is implemented as a platform-independent Qt/C++
+wrapper around the platform-dependent GLX, WGL, or AGL C APIs. The
+functionality provided is very similar to Mark Kilgard's GLUT library,
+but with much more non-OpenGL-specific GUI functionality, i.e. the
+whole Qt API.
+
+\section1 Installation
+
+When you install Qt for X11, the configure script will autodetect if
+OpenGL headers and libraries are installed on your system, and if so,
+it will include the Qt OpenGL module in the Qt library. (If your
+OpenGL headers or libraries are placed in a non-standard directory,
+you may need to change the QMAKE_INCDIR_OPENGL and/or
+QMAKE_LIBDIR_OPENGL in the config file for your system). Some
+configurations require threading to be enabled for OpenGL, so if
+OpenGL is not detected, try \c{configure -thread}.
+
+When you install Qt for Windows, the Qt OpenGL module is always
+included.
+
+The Qt OpenGL module is not licensed for use with the Qt Professional
+Edition. Consider upgrading to the Qt Enterprise Edition if you
+require OpenGL support.
+
+Note about using Mesa on X11: Mesa versions earlier than 3.1 would use
+the name "MesaGL" and "MesaGLU" for the libraries, instead of "GL" and
+"GLU". If you want to use a pre-3.1 version of Mesa, you must change
+the Makefiles to use these library names instead. The easiest way to
+do this is to edit the QMAKE_LIBS_OPENGL line in the config file you
+are using, changing "-lGL -lGLU" to "-lMesaGL -lMesaGLU"; then run
+"configure" again.
+
+\section1 The QGL Classes
+
+The OpenGL support classes in Qt are:
+\list
+\i \link QGLWidget QGLWidget\endlink: An easy-to-use Qt
+ widget for rendering OpenGL scenes.
+\i \link QGLContext QGLContext\endlink: Encapsulates an OpenGL rendering context.
+\i \link QGLFormat QGLFormat\endlink: Specifies the
+display format of a rendering context.
+\i \link QGLColormap QGLColormap\endlink: Handles indexed
+colormaps in GL-index mode.
+\endlist
+
+Many applications only need the high-level QGLWidget class. The other
+QGL classes provide advanced features. X11 users might like to read
+the notes on \link opengl-x11-overlays.html overlays\endlink.
+
+See also the \link opengl-examples.html OpenGL examples\endlink.
+
+The QGL documentation assumes that you are familiar with OpenGL
+programming. If you're new to the subject a good starting point is
+\l{http://www.opengl.org/}.
+
+
+<sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+United States and other countries.
+
+*/
+
+/*!
+ \enum QGL::FormatOption
+
+ This enum specifies the format options.
+
+ \value DoubleBuffer
+ \value DepthBuffer
+ \value Rgba
+ \value AlphaChannel
+ \value AccumBuffer
+ \value StencilBuffer
+ \value StereoBuffers
+ \value DirectRendering
+ \value HasOverlay
+ \value SingleBuffer
+ \value NoDepthBuffer
+ \value ColorIndex
+ \value NoAlphaChannel
+ \value NoAccumBuffer
+ \value NoStencilBuffer
+ \value NoStereoBuffers
+ \value IndirectRendering
+ \value NoOverlay
+*/
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
new file mode 100644
index 0000000..55fa07e
--- /dev/null
+++ b/src/opengl/qgl.h
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Definition of OpenGL classes for Qt
+**
+** Created : 970112
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef QGL_H
+#define QGL_H
+
+#ifndef QT_H
+#include "qwidget.h"
+#include "qglcolormap.h"
+#endif // QT_H
+
+#if !defined( QT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL )
+#define QM_EXPORT_OPENGL
+#else
+#define QM_EXPORT_OPENGL Q_EXPORT
+#endif
+
+#ifndef QT_NO_COMPAT
+#define QGL_VERSION 450
+#define QGL_VERSION_STR "4.5"
+QM_EXPORT_OPENGL inline const char *qGLVersion() {
+ qObsolete( 0, "qGLVersion", "qVersion" );
+ return QGL_VERSION_STR;
+}
+#endif
+
+#if defined(Q_WS_WIN)
+# include "qt_windows.h"
+#endif
+
+#if defined(Q_WS_MAC)
+#if !defined( QMAC_OPENGL_DOUBLEBUFFER )
+/* This macro is different now. If the macro is not defined QGLWidget will
+ * try to determine when you need double buffering. If set to 0 it will
+ * never double buffer and *can* be acclerated. If set to 1 (the default)
+ * it will always double buffer. Unlike before the value of this macro does
+ * not upset binary compatability either. */
+#if QT_MACOSX_VERSION >= 0x1020
+# define QMAC_OPENGL_DOUBLEBUFFER 0
+#endif
+#endif
+# include <OpenGL/gl.h>
+# include <OpenGL/glu.h>
+#else
+# include <GL/gl.h>
+# include <GL/glu.h>
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+class QGLCmap;
+#endif
+
+class QPixmap;
+#if defined(Q_WS_X11)
+class QGLOverlayWidget;
+#endif
+
+// Namespace class:
+class QM_EXPORT_OPENGL QGL
+{
+public:
+ enum FormatOption {
+ DoubleBuffer = 0x0001,
+ DepthBuffer = 0x0002,
+ Rgba = 0x0004,
+ AlphaChannel = 0x0008,
+ AccumBuffer = 0x0010,
+ StencilBuffer = 0x0020,
+ StereoBuffers = 0x0040,
+ DirectRendering = 0x0080,
+ HasOverlay = 0x0100,
+ SingleBuffer = DoubleBuffer << 16,
+ NoDepthBuffer = DepthBuffer << 16,
+ ColorIndex = Rgba << 16,
+ NoAlphaChannel = AlphaChannel << 16,
+ NoAccumBuffer = AccumBuffer << 16,
+ NoStencilBuffer = StencilBuffer << 16,
+ NoStereoBuffers = StereoBuffers << 16,
+ IndirectRendering = DirectRendering << 16,
+ NoOverlay = HasOverlay << 16
+ };
+};
+
+
+
+class QM_EXPORT_OPENGL QGLFormat : public QGL
+{
+public:
+ QGLFormat();
+ QGLFormat( int options, int plane = 0 );
+
+ bool doubleBuffer() const;
+ void setDoubleBuffer( bool enable );
+ bool depth() const;
+ void setDepth( bool enable );
+ bool rgba() const;
+ void setRgba( bool enable );
+ bool alpha() const;
+ void setAlpha( bool enable );
+ bool accum() const;
+ void setAccum( bool enable );
+ bool stencil() const;
+ void setStencil( bool enable );
+ bool stereo() const;
+ void setStereo( bool enable );
+ bool directRendering() const;
+ void setDirectRendering( bool enable );
+ bool hasOverlay() const;
+ void setOverlay( bool enable );
+
+ int plane() const;
+ void setPlane( int plane );
+
+ void setOption( FormatOption opt );
+ bool testOption( FormatOption opt ) const;
+
+ static QGLFormat defaultFormat();
+ static void setDefaultFormat( const QGLFormat& f );
+
+ static QGLFormat defaultOverlayFormat();
+ static void setDefaultOverlayFormat( const QGLFormat& f );
+
+ static bool hasOpenGL();
+ static bool hasOpenGLOverlays();
+
+ friend QM_EXPORT_OPENGL bool operator==( const QGLFormat&,
+ const QGLFormat& );
+ friend QM_EXPORT_OPENGL bool operator!=( const QGLFormat&,
+ const QGLFormat& );
+private:
+ uint opts;
+ int pln;
+};
+
+
+QM_EXPORT_OPENGL bool operator==( const QGLFormat&, const QGLFormat& );
+QM_EXPORT_OPENGL bool operator!=( const QGLFormat&, const QGLFormat& );
+
+class QM_EXPORT_OPENGL QGLContext : public QGL
+{
+public:
+ QGLContext( const QGLFormat& format, QPaintDevice* device );
+ QGLContext( const QGLFormat& format );
+ virtual ~QGLContext();
+
+ virtual bool create( const QGLContext* shareContext = 0 );
+ bool isValid() const;
+ bool isSharing() const;
+ virtual void reset();
+
+ QGLFormat format() const;
+ QGLFormat requestedFormat() const;
+ virtual void setFormat( const QGLFormat& format );
+
+ virtual void makeCurrent();
+ virtual void swapBuffers() const;
+
+ QPaintDevice* device() const;
+
+ QColor overlayTransparentColor() const;
+
+ static const QGLContext* currentContext();
+
+protected:
+ virtual bool chooseContext( const QGLContext* shareContext = 0 );
+ virtual void doneCurrent(); // ### 4.0: make this public - needed for multithreading stuff
+
+#if defined(Q_WS_WIN)
+ virtual int choosePixelFormat( void* pfd, HDC pdc );
+#endif
+#if defined(Q_WS_X11)
+ virtual void* tryVisual( const QGLFormat& f, int bufDepth = 1 );
+ virtual void* chooseVisual();
+#endif
+#if defined(Q_WS_MAC)
+ virtual void* chooseMacVisual(GDHandle);
+#endif
+
+ bool deviceIsPixmap() const;
+ bool windowCreated() const;
+ void setWindowCreated( bool on );
+ bool initialized() const;
+ void setInitialized( bool on );
+ void generateFontDisplayLists( const QFont & fnt, int listBase );
+
+ uint colorIndex( const QColor& c ) const;
+ void setValid( bool valid );
+ void setDevice( QPaintDevice *pDev );
+
+protected:
+#if defined(Q_WS_WIN)
+ HGLRC rc;
+ HDC dc;
+ WId win;
+ int pixelFormatId;
+ QGLCmap* cmap;
+#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
+ void* vi;
+ void* cx;
+#if defined(Q_WS_X11)
+ Q_UINT32 gpm;
+#endif
+#endif
+ QGLFormat glFormat;
+ QGLFormat reqFormat;
+ static QGLContext* currentCtx;
+
+private:
+ void init( QPaintDevice *dev = 0 );
+ class Private {
+ public:
+ bool valid;
+ bool sharing;
+ bool initDone;
+ bool crWin;
+ QPaintDevice* paintDevice;
+ QColor transpColor;
+#ifdef Q_WS_MAC
+ QRect oldR;
+#endif
+ };
+ Private* d;
+
+ friend class QGLWidget;
+#ifdef Q_WS_MAC
+ void fixBufferRect();
+#endif
+
+private: // Disabled copy constructor and operator=
+ QGLContext() {}
+ QGLContext( const QGLContext& ) {}
+ QGLContext& operator=( const QGLContext& ) { return *this; }
+};
+
+
+
+
+class QM_EXPORT_OPENGL QGLWidget : public QWidget, public QGL
+{
+ Q_OBJECT
+public:
+ QGLWidget( QWidget* parent=0, const char* name=0,
+ const QGLWidget* shareWidget = 0, WFlags f=0 );
+ QGLWidget( QGLContext *context, QWidget* parent, const char* name=0,
+ const QGLWidget* shareWidget = 0, WFlags f=0 );
+ QGLWidget( const QGLFormat& format, QWidget* parent=0, const char* name=0,
+ const QGLWidget* shareWidget = 0, WFlags f=0 );
+ ~QGLWidget();
+
+ void qglColor( const QColor& c ) const;
+ void qglClearColor( const QColor& c ) const;
+
+ bool isValid() const;
+ bool isSharing() const;
+ virtual void makeCurrent();
+ void doneCurrent();
+
+ bool doubleBuffer() const;
+ virtual void swapBuffers();
+
+ QGLFormat format() const;
+#ifndef Q_QDOC
+ virtual void setFormat( const QGLFormat& format );
+#endif
+
+ const QGLContext* context() const;
+#ifndef Q_QDOC
+ virtual void setContext( QGLContext* context,
+ const QGLContext* shareContext = 0,
+ bool deleteOldContext = TRUE );
+#endif
+
+ virtual QPixmap renderPixmap( int w = 0, int h = 0,
+ bool useContext = FALSE );
+ virtual QImage grabFrameBuffer( bool withAlpha = FALSE );
+
+ virtual void makeOverlayCurrent();
+ const QGLContext* overlayContext() const;
+
+ static QImage convertToGLFormat( const QImage& img );
+
+ void setMouseTracking( bool enable );
+ virtual void reparent( QWidget* parent, WFlags f, const QPoint& p,
+ bool showIt = FALSE );
+
+ const QGLColormap & colormap() const;
+ void setColormap( const QGLColormap & map );
+
+ void renderText( int x, int y, const QString & str,
+ const QFont & fnt = QFont(), int listBase = 2000 );
+ void renderText( double x, double y, double z, const QString & str,
+ const QFont & fnt = QFont(), int listBase = 2000 );
+public slots:
+ virtual void updateGL();
+ virtual void updateOverlayGL();
+
+protected:
+ virtual void initializeGL();
+ virtual void resizeGL( int w, int h );
+ virtual void paintGL();
+
+ virtual void initializeOverlayGL();
+ virtual void resizeOverlayGL( int w, int h );
+ virtual void paintOverlayGL();
+
+ void setAutoBufferSwap( bool on );
+ bool autoBufferSwap() const;
+
+ void paintEvent( QPaintEvent* );
+ void resizeEvent( QResizeEvent* );
+
+ virtual void glInit();
+ virtual void glDraw();
+
+private:
+ int displayListBase( const QFont & fnt, int listBase );
+ void cleanupColormaps();
+ void init( QGLContext *context, const QGLWidget* shareWidget );
+ bool renderCxPm( QPixmap* pm );
+ QGLContext* glcx;
+ bool autoSwap;
+
+ QGLColormap cmap;
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ QGLContext* olcx;
+#elif defined(Q_WS_X11)
+ QGLOverlayWidget* olw;
+ friend class QGLOverlayWidget;
+#endif
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ QGLWidget( const QGLWidget& );
+ QGLWidget& operator=( const QGLWidget& );
+#endif
+
+#if defined(Q_WS_MAC)
+private:
+ const QGLContext *slcx;
+ uint pending_fix : 1,
+ glcx_dblbuf : 2,
+ dblbuf : 1,
+ clp_serial : 15;
+ QPixmap *gl_pix;
+ QGLFormat req_format;
+
+ void macInternalRecreateContext( QGLContext *ctx,
+ const QGLContext* = NULL,
+ bool update = TRUE );
+ bool macInternalDoubleBuffer( bool fix = TRUE );
+ virtual void setRegionDirty( bool );
+ virtual void macWidgetChangedWindow();
+#endif
+private slots:
+ void macInternalFixBufferRect();
+};
+
+
+//
+// QGLFormat inline functions
+//
+
+inline bool QGLFormat::doubleBuffer() const
+{
+ return testOption( DoubleBuffer );
+}
+
+inline bool QGLFormat::depth() const
+{
+ return testOption( DepthBuffer );
+}
+
+inline bool QGLFormat::rgba() const
+{
+ return testOption( Rgba );
+}
+
+inline bool QGLFormat::alpha() const
+{
+ return testOption( AlphaChannel );
+}
+
+inline bool QGLFormat::accum() const
+{
+ return testOption( AccumBuffer );
+}
+
+inline bool QGLFormat::stencil() const
+{
+ return testOption( StencilBuffer );
+}
+
+inline bool QGLFormat::stereo() const
+{
+ return testOption( StereoBuffers );
+}
+
+inline bool QGLFormat::directRendering() const
+{
+ return testOption( DirectRendering );
+}
+
+inline bool QGLFormat::hasOverlay() const
+{
+ return testOption( HasOverlay );
+}
+
+//
+// QGLContext inline functions
+//
+
+inline bool QGLContext::isValid() const
+{
+ return d->valid;
+}
+
+inline void QGLContext::setValid( bool valid )
+{
+ d->valid = valid;
+}
+
+inline bool QGLContext::isSharing() const
+{
+ return d->sharing;
+}
+
+inline QGLFormat QGLContext::format() const
+{
+ return glFormat;
+}
+
+inline QGLFormat QGLContext::requestedFormat() const
+{
+ return reqFormat;
+}
+
+inline QPaintDevice* QGLContext::device() const
+{
+ return d->paintDevice;
+}
+
+inline bool QGLContext::deviceIsPixmap() const
+{
+ return d->paintDevice->devType() == QInternal::Pixmap;
+}
+
+
+inline bool QGLContext::windowCreated() const
+{
+ return d->crWin;
+}
+
+
+inline void QGLContext::setWindowCreated( bool on )
+{
+ d->crWin = on;
+}
+
+inline bool QGLContext::initialized() const
+{
+ return d->initDone;
+}
+
+inline void QGLContext::setInitialized( bool on )
+{
+ d->initDone = on;
+}
+
+inline const QGLContext* QGLContext::currentContext()
+{
+ return currentCtx;
+}
+
+//
+// QGLWidget inline functions
+//
+
+inline QGLFormat QGLWidget::format() const
+{
+ return glcx->format();
+}
+
+inline const QGLContext *QGLWidget::context() const
+{
+ return glcx;
+}
+
+inline bool QGLWidget::doubleBuffer() const
+{
+ return glcx->format().doubleBuffer();
+}
+
+inline void QGLWidget::setAutoBufferSwap( bool on )
+{
+ autoSwap = on;
+}
+
+inline bool QGLWidget::autoBufferSwap() const
+{
+ return autoSwap;
+}
+
+#endif
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
new file mode 100644
index 0000000..a8abef8
--- /dev/null
+++ b/src/opengl/qgl_x11.cpp
@@ -0,0 +1,1406 @@
+/****************************************************************************
+**
+** Implementation of OpenGL classes for Qt
+**
+** Created : 970112
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qgl.h"
+
+#if defined(Q_WS_X11)
+
+#include "qmap.h"
+#include "qpixmap.h"
+#include "qapplication.h"
+
+#include "qintdict.h"
+#include "private/qfontengine_p.h"
+
+#define INT8 dummy_INT8
+#define INT32 dummy_INT32
+#include <GL/glx.h>
+#undef INT8
+#undef INT32
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+
+// POSIX Large File Support redefines truncate -> truncate64
+#if defined(truncate)
+# undef truncate
+#endif
+
+#ifndef QT_DLOPEN_OPENGL
+extern "C" {
+ Status XmuLookupStandardColormap( Display *dpy, int screen, VisualID visualid,
+ unsigned int depth, Atom property,
+ Bool replace, Bool retain );
+}
+#endif
+
+#include "qgl_x11_p.h"
+#ifdef QT_DLOPEN_OPENGL
+#include "qlibrary.h"
+
+extern "C" {
+_glCallLists qt_glCallLists;
+_glClearColor qt_glClearColor;
+_glClearIndex qt_glClearIndex;
+_glColor3ub qt_glColor3ub;
+_glDeleteLists qt_glDeleteLists;
+_glDrawBuffer qt_glDrawBuffer;
+_glFlush qt_glFlush;
+_glIndexi qt_glIndexi;
+_glListBase qt_glListBase;
+_glLoadIdentity qt_glLoadIdentity;
+_glMatrixMode qt_glMatrixMode;
+_glOrtho qt_glOrtho;
+_glPopAttrib qt_glPopAttrib;
+_glPopMatrix qt_glPopMatrix;
+_glPushAttrib qt_glPushAttrib;
+_glPushMatrix qt_glPushMatrix;
+_glRasterPos2i qt_glRasterPos2i;
+_glRasterPos3d qt_glRasterPos3d;
+_glReadPixels qt_glReadPixels;
+_glViewport qt_glViewport;
+_glPixelStorei qt_glPixelStorei;
+_glBitmap qt_glBitmap;
+_glDrawPixels qt_glDrawPixels;
+_glNewList qt_glNewList;
+_glGetFloatv qt_glGetFloatv;
+_glGetIntegerv qt_glGetIntegerv;
+_glEndList qt_glEndList;
+
+_glXChooseVisual qt_glXChooseVisual;
+_glXCreateContext qt_glXCreateContext;
+_glXCreateGLXPixmap qt_glXCreateGLXPixmap;
+_glXDestroyContext qt_glXDestroyContext;
+_glXDestroyGLXPixmap qt_glXDestroyGLXPixmap;
+_glXGetClientString qt_glXGetClientString;
+_glXGetConfig qt_glXGetConfig;
+_glXIsDirect qt_glXIsDirect;
+_glXMakeCurrent qt_glXMakeCurrent;
+_glXQueryExtension qt_glXQueryExtension;
+_glXQueryExtensionsString qt_glXQueryExtensionsString;
+_glXQueryServerString qt_glXQueryServerString;
+_glXSwapBuffers qt_glXSwapBuffers;
+_glXUseXFont qt_glXUseXFont;
+_glXWaitX qt_glXWaitX;
+};
+
+bool qt_resolve_gl_symbols(bool fatal)
+{
+ static bool gl_syms_resolved = FALSE;
+ if (gl_syms_resolved)
+ return TRUE;
+
+ QLibrary gl("GL.so.1");
+ gl.setAutoUnload(FALSE);
+
+ qt_glCallLists = (_glCallLists) gl.resolve("glCallLists");
+
+ if (!qt_glCallLists) { // if this fails the rest will surely fail
+ if (fatal)
+ qFatal("Unable to resolve GL/GLX symbols - please check your GL library installation.");
+ return FALSE;
+ }
+
+ qt_glClearColor = (_glClearColor) gl.resolve("glClearColor");
+ qt_glClearIndex = (_glClearIndex) gl.resolve("glClearIndex");
+ qt_glColor3ub = (_glColor3ub) gl.resolve("glColor3ub");
+ qt_glDeleteLists = (_glDeleteLists) gl.resolve("glDeleteLists");
+ qt_glDrawBuffer = (_glDrawBuffer) gl.resolve("glDrawBuffer");
+ qt_glFlush = (_glFlush) gl.resolve("glFlush");
+ qt_glIndexi = (_glIndexi) gl.resolve("glIndexi");
+ qt_glListBase = (_glListBase) gl.resolve("glListBase");
+ qt_glLoadIdentity = (_glLoadIdentity) gl.resolve("glLoadIdentity");
+ qt_glMatrixMode = (_glMatrixMode) gl.resolve("glMatrixMode");
+ qt_glOrtho = (_glOrtho) gl.resolve("glOrtho");
+ qt_glPopAttrib = (_glPopAttrib) gl.resolve("glPopAttrib");
+ qt_glPopMatrix = (_glPopMatrix) gl.resolve("glPopMatrix");
+ qt_glPushAttrib = (_glPushAttrib) gl.resolve("glPushAttrib");
+ qt_glPushMatrix = (_glPushMatrix) gl.resolve("glPushMatrix");
+ qt_glRasterPos2i = (_glRasterPos2i) gl.resolve("glRasterPos2i");
+ qt_glRasterPos3d = (_glRasterPos3d) gl.resolve("glRasterPos3d");
+ qt_glReadPixels = (_glReadPixels) gl.resolve("glReadPixels");
+ qt_glViewport = (_glViewport) gl.resolve("glViewport");
+ qt_glPixelStorei = (_glPixelStorei) gl.resolve("glPixelStorei");
+ qt_glBitmap = (_glBitmap) gl.resolve("glBitmap");
+ qt_glDrawPixels = (_glDrawPixels) gl.resolve("glDrawPixels");
+ qt_glNewList = (_glNewList) gl.resolve("glNewList");
+ qt_glGetFloatv = (_glGetFloatv) gl.resolve("glGetFloatv");
+ qt_glGetIntegerv = (_glGetIntegerv) gl.resolve("glGetIntegerv");
+ qt_glEndList = (_glEndList) gl.resolve("glEndList");
+
+ qt_glXChooseVisual = (_glXChooseVisual) gl.resolve("glXChooseVisual");
+ qt_glXCreateContext = (_glXCreateContext) gl.resolve("glXCreateContext");
+ qt_glXCreateGLXPixmap = (_glXCreateGLXPixmap) gl.resolve("glXCreateGLXPixmap");
+ qt_glXDestroyContext = (_glXDestroyContext) gl.resolve("glXDestroyContext");
+ qt_glXDestroyGLXPixmap = (_glXDestroyGLXPixmap) gl.resolve("glXDestroyGLXPixmap");
+ qt_glXGetClientString = (_glXGetClientString) gl.resolve("glXGetClientString");
+ qt_glXGetConfig = (_glXGetConfig) gl.resolve("glXGetConfig");
+ qt_glXIsDirect = (_glXIsDirect) gl.resolve("glXIsDirect");
+ qt_glXMakeCurrent = (_glXMakeCurrent) gl.resolve("glXMakeCurrent");
+ qt_glXQueryExtension = (_glXQueryExtension) gl.resolve("glXQueryExtension");
+ qt_glXQueryExtensionsString = (_glXQueryExtensionsString) gl.resolve("glXQueryExtensionsString");
+ qt_glXQueryServerString = (_glXQueryServerString) gl.resolve("glXQueryServerString");
+ qt_glXSwapBuffers = (_glXSwapBuffers) gl.resolve("glXSwapBuffers");
+ qt_glXUseXFont = (_glXUseXFont) gl.resolve("glXUseXFont");
+ qt_glXWaitX = (_glXWaitX) gl.resolve("glXWaitX");
+ gl_syms_resolved = TRUE;
+ return TRUE;
+}
+#endif // QT_DLOPEN_OPENGL
+
+
+/*
+ The choose_cmap function is internal and used by QGLWidget::setContext()
+ and GLX (not Windows). If the application can't find any sharable
+ colormaps, it must at least create as few colormaps as possible. The
+ dictionary solution below ensures only one colormap is created per visual.
+ Colormaps are also deleted when the application terminates.
+*/
+
+struct CMapEntry {
+ CMapEntry();
+ ~CMapEntry();
+ Colormap cmap;
+ bool alloc;
+ XStandardColormap scmap;
+};
+
+CMapEntry::CMapEntry()
+{
+ cmap = 0;
+ alloc = FALSE;
+ scmap.colormap = 0;
+}
+
+CMapEntry::~CMapEntry()
+{
+ if ( alloc )
+ XFreeColormap( QPaintDevice::x11AppDisplay(), cmap );
+}
+
+static QIntDict<CMapEntry> *cmap_dict = 0;
+static bool mesa_gl = FALSE;
+static QIntDict< QMap<int, QRgb> > *qglcmap_dict = 0;
+
+static void cleanup_cmaps()
+{
+ if (cmap_dict) {
+ cmap_dict->setAutoDelete(TRUE);
+ delete cmap_dict;
+ cmap_dict = 0;
+ }
+ if (qglcmap_dict) {
+ qglcmap_dict->setAutoDelete(TRUE);
+ delete qglcmap_dict;
+ qglcmap_dict = 0;
+ }
+}
+
+static Colormap choose_cmap( Display *dpy, XVisualInfo *vi )
+{
+ if ( !cmap_dict ) {
+ cmap_dict = new QIntDict<CMapEntry>;
+ const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
+ if ( v )
+ mesa_gl = strstr(v,"Mesa") != 0;
+ qAddPostRoutine( cleanup_cmaps );
+ }
+
+ CMapEntry *x = cmap_dict->find( (long) vi->visualid + ( vi->screen * 256 ) );
+ if ( x ) // found colormap for visual
+ return x->cmap;
+
+ x = new CMapEntry();
+
+ XStandardColormap *c;
+ int n, i;
+
+ // qDebug( "Choosing cmap for vID %0x", vi->visualid );
+
+ if ( vi->visualid ==
+ XVisualIDFromVisual( (Visual*)QPaintDevice::x11AppVisual( vi->screen ) ) ) {
+ // qDebug( "Using x11AppColormap" );
+ return QPaintDevice::x11AppColormap( vi->screen );
+ }
+
+ if ( mesa_gl ) { // we're using MesaGL
+ Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", TRUE );
+ if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 ) {
+ if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
+ hp_cmaps) ) {
+ i = 0;
+ while ( i < n && x->cmap == 0 ) {
+ if ( c[i].visualid == vi->visual->visualid ) {
+ x->cmap = c[i].colormap;
+ x->scmap = c[i];
+ //qDebug( "Using HP_RGB scmap" );
+
+ }
+ i++;
+ }
+ XFree( (char *)c );
+ }
+ }
+ }
+#if !defined(Q_OS_SOLARIS)
+ if ( !x->cmap ) {
+#ifdef QT_DLOPEN_OPENGL
+ typedef Status (*_XmuLookupStandardColormap)( Display *dpy, int screen, VisualID visualid, unsigned int depth,
+ Atom property, Bool replace, Bool retain );
+ _XmuLookupStandardColormap qt_XmuLookupStandardColormap;
+ qt_XmuLookupStandardColormap = (_XmuLookupStandardColormap) QLibrary::resolve("Xmu.so.6", "XmuLookupStandardColormap");
+ if (!qt_XmuLookupStandardColormap)
+ qFatal("Unable to resolve Xmu symbols - please check your Xmu library installation.");
+#define XmuLookupStandardColormap qt_XmuLookupStandardColormap
+
+#endif
+
+ if ( XmuLookupStandardColormap(dpy,vi->screen,vi->visualid,vi->depth,
+ XA_RGB_DEFAULT_MAP,FALSE,TRUE) ) {
+ if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
+ XA_RGB_DEFAULT_MAP) ) {
+ i = 0;
+ while ( i < n && x->cmap == 0 ) {
+ if ( c[i].visualid == vi->visualid ) {
+ x->cmap = c[i].colormap;
+ x->scmap = c[i];
+ //qDebug( "Using RGB_DEFAULT scmap" );
+ }
+ i++;
+ }
+ XFree( (char *)c );
+ }
+ }
+ }
+#endif
+ if ( !x->cmap ) { // no shared cmap found
+ x->cmap = XCreateColormap( dpy, RootWindow(dpy,vi->screen), vi->visual,
+ AllocNone );
+ x->alloc = TRUE;
+ // qDebug( "Allocating cmap" );
+ }
+
+ // associate cmap with visualid
+ cmap_dict->insert( (long) vi->visualid + ( vi->screen * 256 ), x );
+ return x->cmap;
+}
+
+struct TransColor
+{
+ VisualID vis;
+ int screen;
+ long color;
+};
+
+static QMemArray<TransColor> trans_colors;
+static int trans_colors_init = FALSE;
+
+
+static void find_trans_colors()
+{
+ struct OverlayProp {
+ long visual;
+ long type;
+ long value;
+ long layer;
+ };
+
+ trans_colors_init = TRUE;
+
+ Display* appDisplay = QPaintDevice::x11AppDisplay();
+
+ int scr;
+ int lastsize = 0;
+ for ( scr = 0; scr < ScreenCount( appDisplay ); scr++ ) {
+ QWidget* rootWin = QApplication::desktop()->screen( scr );
+ if ( !rootWin )
+ return; // Should not happen
+ Atom overlayVisualsAtom = XInternAtom( appDisplay,
+ "SERVER_OVERLAY_VISUALS", True );
+ if ( overlayVisualsAtom == None )
+ return; // Server has no overlays
+
+ Atom actualType;
+ int actualFormat;
+ ulong nItems;
+ ulong bytesAfter;
+ OverlayProp* overlayProps = 0;
+ int res = XGetWindowProperty( appDisplay, rootWin->winId(),
+ overlayVisualsAtom, 0, 10000, False,
+ overlayVisualsAtom, &actualType,
+ &actualFormat, &nItems, &bytesAfter,
+ (uchar**)&overlayProps );
+
+ if ( res != Success || actualType != overlayVisualsAtom
+ || actualFormat != 32 || nItems < 4 || !overlayProps )
+ return; // Error reading property
+
+ int numProps = nItems / 4;
+ trans_colors.resize( lastsize + numProps );
+ int j = lastsize;
+ for ( int i = 0; i < numProps; i++ ) {
+ if ( overlayProps[i].type == 1 ) {
+ trans_colors[j].vis = (VisualID)overlayProps[i].visual;
+ trans_colors[j].screen = scr;
+ trans_colors[j].color = (int)overlayProps[i].value;
+ j++;
+ }
+ }
+ XFree( overlayProps );
+ lastsize = j;
+ trans_colors.truncate( lastsize );
+ }
+}
+
+
+/*****************************************************************************
+ QGLFormat UNIX/GLX-specific code
+ *****************************************************************************/
+
+bool QGLFormat::hasOpenGL()
+{
+ if (!qt_resolve_gl_symbols(FALSE))
+ return FALSE;
+ return glXQueryExtension(qt_xdisplay(),0,0) != 0;
+}
+
+
+bool QGLFormat::hasOpenGLOverlays()
+{
+ qt_resolve_gl_symbols();
+ if ( !trans_colors_init )
+ find_trans_colors();
+ return trans_colors.size() > 0;
+}
+
+
+
+/*****************************************************************************
+ QGLContext UNIX/GLX-specific code
+ *****************************************************************************/
+
+bool QGLContext::chooseContext( const QGLContext* shareContext )
+{
+ Display* disp = d->paintDevice->x11Display();
+ vi = chooseVisual();
+ if ( !vi )
+ return FALSE;
+
+ if ( deviceIsPixmap() &&
+ (((XVisualInfo*)vi)->depth != d->paintDevice->x11Depth() ||
+ ((XVisualInfo*)vi)->screen != d->paintDevice->x11Screen()) )
+ {
+ XFree( vi );
+ XVisualInfo appVisInfo;
+ memset( &appVisInfo, 0, sizeof(XVisualInfo) );
+ appVisInfo.visualid = XVisualIDFromVisual( (Visual*)d->paintDevice->x11Visual() );
+ appVisInfo.screen = d->paintDevice->x11Screen();
+ int nvis;
+ vi = XGetVisualInfo( disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis );
+ if ( !vi )
+ return FALSE;
+
+ int useGL;
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL );
+ if ( !useGL )
+ return FALSE; //# Chickening out already...
+ }
+ int res;
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res );
+ glFormat.setPlane( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res );
+ glFormat.setDoubleBuffer( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res );
+ glFormat.setDepth( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res );
+ glFormat.setRgba( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res );
+ glFormat.setAlpha( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res );
+ glFormat.setAccum( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res );
+ glFormat.setStencil( res );
+ glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res );
+ glFormat.setStereo( res );
+
+ Bool direct = format().directRendering() ? True : False;
+
+ if ( shareContext &&
+ ( !shareContext->isValid() || !shareContext->cx ) ) {
+#if defined(QT_CHECK_NULL)
+ qWarning("QGLContext::chooseContext(): Cannot share with invalid context");
+#endif
+ shareContext = 0;
+ }
+
+ // 1. Sharing between rgba and color-index will give wrong colors.
+ // 2. Contexts cannot be shared btw. direct/non-direct renderers.
+ // 3. Pixmaps cannot share contexts that are set up for direct rendering.
+ if ( shareContext && (format().rgba() != shareContext->format().rgba() ||
+ (deviceIsPixmap() &&
+ glXIsDirect( disp, (GLXContext)shareContext->cx ))))
+ shareContext = 0;
+
+ cx = 0;
+ if ( shareContext ) {
+ cx = glXCreateContext( disp, (XVisualInfo *)vi,
+ (GLXContext)shareContext->cx, direct );
+ if ( cx )
+ d->sharing = TRUE;
+ }
+ if ( !cx )
+ cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct );
+ if ( !cx )
+ return FALSE;
+ glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) );
+ if ( deviceIsPixmap() ) {
+#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT)
+ gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi,
+ d->paintDevice->handle(),
+ choose_cmap( disp, (XVisualInfo *)vi ) );
+#else
+ gpm = (Q_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi,
+ d->paintDevice->handle() );
+#endif
+ if ( !gpm )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*!
+ <strong>X11 only</strong>: This virtual function tries to find a
+ visual that matches the format, reducing the demands if the original
+ request cannot be met.
+
+ The algorithm for reducing the demands of the format is quite
+ simple-minded, so override this method in your subclass if your
+ application has spcific requirements on visual selection.
+
+ \sa chooseContext()
+*/
+
+void *QGLContext::chooseVisual()
+{
+ static int bufDepths[] = { 8, 4, 2, 1 }; // Try 16, 12 also?
+ //todo: if pixmap, also make sure that vi->depth == pixmap->depth
+ void* vis = 0;
+ int i = 0;
+ bool fail = FALSE;
+ QGLFormat fmt = format();
+ bool tryDouble = !fmt.doubleBuffer(); // Some GL impl's only have double
+ bool triedDouble = FALSE;
+ while( !fail && !( vis = tryVisual( fmt, bufDepths[i] ) ) ) {
+ if ( !fmt.rgba() && bufDepths[i] > 1 ) {
+ i++;
+ continue;
+ }
+ if ( tryDouble ) {
+ fmt.setDoubleBuffer( TRUE );
+ tryDouble = FALSE;
+ triedDouble = TRUE;
+ continue;
+ }
+ else if ( triedDouble ) {
+ fmt.setDoubleBuffer( FALSE );
+ triedDouble = FALSE;
+ }
+ if ( fmt.stereo() ) {
+ fmt.setStereo( FALSE );
+ continue;
+ }
+ if ( fmt.accum() ) {
+ fmt.setAccum( FALSE );
+ continue;
+ }
+ if ( fmt.stencil() ) {
+ fmt.setStencil( FALSE );
+ continue;
+ }
+ if ( fmt.alpha() ) {
+ fmt.setAlpha( FALSE );
+ continue;
+ }
+ if ( fmt.depth() ) {
+ fmt.setDepth( FALSE );
+ continue;
+ }
+ if ( fmt.doubleBuffer() ) {
+ fmt.setDoubleBuffer( FALSE );
+ continue;
+ }
+ fail = TRUE;
+ }
+ glFormat = fmt;
+ return vis;
+}
+
+
+/*!
+
+ \internal
+
+ <strong>X11 only</strong>: This virtual function chooses a visual
+ that matches the OpenGL \link format() format\endlink. Reimplement this
+ function in a subclass if you need a custom visual.
+
+ \sa chooseContext()
+*/
+
+void *QGLContext::tryVisual( const QGLFormat& f, int bufDepth )
+{
+ int spec[40];
+ int i = 0;
+ spec[i++] = GLX_LEVEL;
+ spec[i++] = f.plane();
+
+#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
+ static bool useTranspExt = FALSE;
+ static bool useTranspExtChecked = FALSE;
+ if ( f.plane() && !useTranspExtChecked && d->paintDevice ) {
+ QCString estr( glXQueryExtensionsString( d->paintDevice->x11Display(),
+ d->paintDevice->x11Screen() ) );
+ useTranspExt = estr.contains( "GLX_EXT_visual_info" );
+ //# (A bit simplistic; that could theoretically be a substring)
+ if ( useTranspExt ) {
+ QCString cstr( glXGetClientString( d->paintDevice->x11Display(),
+ GLX_VENDOR ) );
+ useTranspExt = !cstr.contains( "Xi Graphics" ); // bug workaround
+ if ( useTranspExt ) {
+ // bug workaround - some systems (eg. FireGL) refuses to return an overlay
+ // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specfied, even if
+ // the implementation supports transparent overlays
+ int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
+ f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
+ None };
+ XVisualInfo * vinf = glXChooseVisual( d->paintDevice->x11Display(),
+ d->paintDevice->x11Screen(), tmpSpec );
+ if ( !vinf ) {
+ useTranspExt = FALSE;
+ }
+ }
+ }
+
+ useTranspExtChecked = TRUE;
+ }
+ if ( f.plane() && useTranspExt ) {
+ // Required to avoid non-transparent overlay visual(!) on some systems
+ spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
+ spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
+ }
+#endif
+
+ if ( f.doubleBuffer() )
+ spec[i++] = GLX_DOUBLEBUFFER;
+ if ( f.depth() ) {
+ spec[i++] = GLX_DEPTH_SIZE;
+ spec[i++] = 1;
+ }
+ if ( f.stereo() ) {
+ spec[i++] = GLX_STEREO;
+ }
+ if ( f.stencil() ) {
+ spec[i++] = GLX_STENCIL_SIZE;
+ spec[i++] = 1;
+ }
+ if ( f.rgba() ) {
+ spec[i++] = GLX_RGBA;
+ spec[i++] = GLX_RED_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_GREEN_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_BLUE_SIZE;
+ spec[i++] = 1;
+ if ( f.alpha() ) {
+ spec[i++] = GLX_ALPHA_SIZE;
+ spec[i++] = 1;
+ }
+ if ( f.accum() ) {
+ spec[i++] = GLX_ACCUM_RED_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_ACCUM_GREEN_SIZE;
+ spec[i++] = 1;
+ spec[i++] = GLX_ACCUM_BLUE_SIZE;
+ spec[i++] = 1;
+ if ( f.alpha() ) {
+ spec[i++] = GLX_ACCUM_ALPHA_SIZE;
+ spec[i++] = 1;
+ }
+ }
+ }
+ else {
+ spec[i++] = GLX_BUFFER_SIZE;
+ spec[i++] = bufDepth;
+ }
+
+ spec[i] = None;
+ return glXChooseVisual( d->paintDevice->x11Display(),
+ d->paintDevice->x11Screen(), spec );
+}
+
+
+void QGLContext::reset()
+{
+ if ( !d->valid )
+ return;
+ doneCurrent();
+ if ( gpm )
+ glXDestroyGLXPixmap( d->paintDevice->x11Display(), (GLXPixmap)gpm );
+ gpm = 0;
+ glXDestroyContext( d->paintDevice->x11Display(), (GLXContext)cx );
+ if ( vi )
+ XFree( vi );
+ vi = 0;
+ cx = 0;
+ d->crWin = FALSE;
+ d->sharing = FALSE;
+ d->valid = FALSE;
+ d->transpColor = QColor();
+ d->initDone = FALSE;
+}
+
+
+void QGLContext::makeCurrent()
+{
+ if ( !d->valid ) {
+#if defined(QT_CHECK_STATE)
+ qWarning("QGLContext::makeCurrent(): Cannot make invalid context current.");
+#endif
+ return;
+ }
+ bool ok = TRUE;
+ if ( deviceIsPixmap() )
+ ok = glXMakeCurrent( d->paintDevice->x11Display(),
+ (GLXPixmap)gpm,
+ (GLXContext)cx );
+
+ else
+ ok = glXMakeCurrent( d->paintDevice->x11Display(),
+ ((QWidget *)d->paintDevice)->winId(),
+ (GLXContext)cx );
+#if defined(QT_CHECK_NULL)
+ // qDebug("makeCurrent: %i, vi=%i, vi->vi=%i, vi->id=%i", (int)this, (int)vi, (int)((XVisualInfo*)vi)->visual, (int)((XVisualInfo*)vi)->visualid );
+ if ( !ok )
+ qWarning("QGLContext::makeCurrent(): Failed.");
+#endif
+ if ( ok )
+ currentCtx = this;
+}
+
+void QGLContext::doneCurrent()
+{
+ glXMakeCurrent( d->paintDevice->x11Display(), 0, 0 );
+ currentCtx = 0;
+}
+
+
+void QGLContext::swapBuffers() const
+{
+ if ( !d->valid )
+ return;
+ if ( !deviceIsPixmap() )
+ glXSwapBuffers( d->paintDevice->x11Display(),
+ ((QWidget *)d->paintDevice)->winId() );
+}
+
+QColor QGLContext::overlayTransparentColor() const
+{
+ //### make more efficient using the transpColor member
+ if ( isValid() ) {
+ if ( !trans_colors_init )
+ find_trans_colors();
+
+ VisualID myVisualId = ((XVisualInfo*)vi)->visualid;
+ int myScreen = ((XVisualInfo*)vi)->screen;
+ for ( int i = 0; i < (int)trans_colors.size(); i++ ) {
+ if ( trans_colors[i].vis == myVisualId &&
+ trans_colors[i].screen == myScreen ) {
+ XColor col;
+ col.pixel = trans_colors[i].color;
+ col.red = col.green = col.blue = 0;
+ col.flags = 0;
+ Display *dpy = d->paintDevice->x11Display();
+ if (col.pixel > (uint) ((XVisualInfo *)vi)->colormap_size - 1)
+ col.pixel = ((XVisualInfo *)vi)->colormap_size - 1;
+ XQueryColor(dpy, choose_cmap(dpy, (XVisualInfo *) vi), &col);
+ uchar r = (uchar)((col.red / 65535.0) * 255.0 + 0.5);
+ uchar g = (uchar)((col.green / 65535.0) * 255.0 + 0.5);
+ uchar b = (uchar)((col.blue / 65535.0) * 255.0 + 0.5);
+ return QColor(qRgb(r,g,b), trans_colors[i].color);
+ }
+ }
+ }
+ return QColor(); // Invalid color
+}
+
+
+uint QGLContext::colorIndex( const QColor& c ) const
+{
+ int screen = ((XVisualInfo *)vi)->screen;
+ if ( isValid() ) {
+ if ( format().plane()
+ && c.pixel( screen ) == overlayTransparentColor().pixel( screen ) )
+ return c.pixel( screen ); // Special; don't look-up
+ if ( ((XVisualInfo*)vi)->visualid ==
+ XVisualIDFromVisual( (Visual*)QPaintDevice::x11AppVisual( screen ) ) )
+ return c.pixel( screen ); // We're using QColor's cmap
+
+ XVisualInfo *info = (XVisualInfo *) vi;
+ CMapEntry *x = cmap_dict->find( (long) info->visualid + ( info->screen * 256 ) );
+ if ( x && !x->alloc) { // It's a standard colormap
+ int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0);
+ int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0);
+ int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0);
+ uint p = x->scmap.base_pixel
+ + ( rf * x->scmap.red_mult )
+ + ( gf * x->scmap.green_mult )
+ + ( bf * x->scmap.blue_mult );
+ return p;
+ } else {
+ if (!qglcmap_dict) {
+ qglcmap_dict = new QIntDict< QMap<int, QRgb> >;
+ }
+ QMap<int, QRgb> *cmap;
+ if ((cmap = qglcmap_dict->find((long) info->visualid)) == 0) {
+ cmap = new QMap<int, QRgb>;
+ qglcmap_dict->insert((long) info->visualid, cmap);
+ }
+
+ // already in the map?
+ QRgb target = c.rgb();
+ QMap<int, QRgb>::Iterator it = cmap->begin();
+ for (; it != cmap->end(); ++it) {
+ if ((*it) == target)
+ return it.key();
+ }
+
+ // need to alloc color
+ unsigned long plane_mask[2];
+ unsigned long color_map_entry;
+ if (!XAllocColorCells (QPaintDevice::x11AppDisplay(), x->cmap, TRUE, plane_mask, 0,
+ &color_map_entry, 1))
+ return c.pixel(screen);
+
+ XColor col;
+ col.flags = DoRed | DoGreen | DoBlue;
+ col.pixel = color_map_entry;
+ col.red = (ushort)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ col.blue = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ XStoreColor(QPaintDevice::x11AppDisplay(), x->cmap, &col);
+
+ cmap->insert(color_map_entry, target);
+ return color_map_entry;
+ }
+ }
+ return 0;
+}
+
+#ifndef QT_NO_XFTFREETYPE
+/*! \internal
+ This is basically a substitute for glxUseXFont() which can only
+ handle XLFD fonts. This version relies on XFT v2 to render the
+ glyphs, but it works with all fonts that XFT2 provides - both
+ antialiased and aliased bitmap and outline fonts.
+*/
+void qgl_use_font(QFontEngineXft *engine, int first, int count, int listBase)
+{
+ GLfloat color[4];
+ glGetFloatv(GL_CURRENT_COLOR, color);
+
+ // save the pixel unpack state
+ GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment;
+ glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes);
+ glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst);
+ glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength);
+ glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows);
+ glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels);
+ glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment);
+
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ Bool antialiased = False;
+#if 0 // disable antialias support for now
+ XftPatternGetBool(engine->pattern(), XFT_ANTIALIAS, 0, &antialiased);
+#endif
+#ifdef QT_XFT2
+ FT_Face face = XftLockFace(engine->font());
+#else
+ FT_Face face = engine->face();
+#endif
+ // start generating font glyphs
+ for (int i = first; i < count; ++i) {
+ int list = listBase + i;
+ GLfloat x0, y0, dx, dy;
+
+ FT_Error err;
+
+ err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT);
+ if (err) {
+ qDebug("failed loading glyph %d from font", i);
+ Q_ASSERT(!err);
+ }
+ err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal
+ : ft_render_mode_mono));
+ if (err) {
+ qDebug("failed rendering glyph %d from font", i);
+ Q_ASSERT(!err);
+ }
+
+ FT_Bitmap bm = face->glyph->bitmap;
+ x0 = face->glyph->metrics.horiBearingX >> 6;
+ y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6;
+ dx = face->glyph->metrics.horiAdvance >> 6;
+ dy = 0;
+ int sz = bm.pitch * bm.rows;
+ uint *aa_glyph = 0;
+ uchar *ua_glyph = 0;
+
+ if (antialiased)
+ aa_glyph = new uint[sz];
+ else
+ ua_glyph = new uchar[sz];
+
+ // convert to GL format
+ for (int y = 0; y < bm.rows; ++y) {
+ for (int x = 0; x < bm.pitch; ++x) {
+ int c1 = y*bm.pitch + x;
+ int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x;
+ if (antialiased) {
+ aa_glyph[c1] = (int(color[0]*255) << 24)
+ | (int(color[1]*255) << 16)
+ | (int(color[2]*255) << 8) | bm.buffer[c2];
+ } else {
+ ua_glyph[c1] = bm.buffer[c2];
+ }
+ }
+ }
+
+ glNewList(list, GL_COMPILE);
+ if (antialiased) {
+ // calling glBitmap() is just a trick to move the current
+ // raster pos, since glGet*() won't work in display lists
+ glBitmap(0, 0, 0, 0, x0, -y0, 0);
+ glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph);
+ glBitmap(0, 0, 0, 0, dx-x0, y0, 0);
+ } else {
+ glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph);
+ }
+ glEndList();
+ antialiased ? delete[] aa_glyph : delete[] ua_glyph;
+ }
+
+#ifdef QT_XFT2
+ XftUnlockFace(engine->font());
+#endif
+
+ // restore pixel unpack settings
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment);
+}
+#endif
+
+void QGLContext::generateFontDisplayLists( const QFont & fnt, int listBase )
+{
+ QFont f(fnt);
+ QFontEngine *engine = f.d->engineForScript(QFont::Latin);
+
+#ifndef QT_NO_XFTFREETYPE
+ if(engine->type() == QFontEngine::Xft) {
+ qgl_use_font((QFontEngineXft *) engine, 0, 256, listBase);
+ return;
+ }
+#endif
+ // glXUseXFont() only works with XLFD font structures and a few GL
+ // drivers crash if 0 is passed as the font handle
+ f.setStyleStrategy(QFont::OpenGLCompatible);
+ if (f.handle() && (engine->type() == QFontEngine::XLFD
+ || engine->type() == QFontEngine::LatinXLFD)) {
+ glXUseXFont((Font) f.handle(), 0, 256, listBase);
+ }
+}
+
+/*****************************************************************************
+ QGLOverlayWidget (Internal overlay class for X11)
+ *****************************************************************************/
+
+class QGLOverlayWidget : public QGLWidget
+{
+ Q_OBJECT
+public:
+ QGLOverlayWidget( const QGLFormat& format, QGLWidget* parent,
+ const char* name=0, const QGLWidget* shareWidget=0 );
+
+protected:
+ void initializeGL();
+ void paintGL();
+ void resizeGL( int w, int h );
+
+private:
+ QGLWidget* realWidget;
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ QGLOverlayWidget( const QGLOverlayWidget& );
+ QGLOverlayWidget& operator=( const QGLOverlayWidget& );
+#endif
+};
+
+
+QGLOverlayWidget::QGLOverlayWidget( const QGLFormat& format, QGLWidget* parent,
+ const char* name,
+ const QGLWidget* shareWidget )
+ : QGLWidget( format, parent, name, shareWidget ? shareWidget->olw : 0 )
+{
+ realWidget = parent;
+}
+
+
+
+void QGLOverlayWidget::initializeGL()
+{
+ QColor transparentColor = context()->overlayTransparentColor();
+ if ( transparentColor.isValid() )
+ qglClearColor( transparentColor );
+ else
+ qWarning( "QGLOverlayWidget::initializeGL(): Could not get transparent color" );
+ realWidget->initializeOverlayGL();
+}
+
+
+void QGLOverlayWidget::resizeGL( int w, int h )
+{
+ glViewport( 0, 0, w, h );
+ realWidget->resizeOverlayGL( w, h );
+}
+
+
+void QGLOverlayWidget::paintGL()
+{
+ realWidget->paintOverlayGL();
+}
+
+#undef Bool
+#include "qgl_x11.moc"
+
+/*****************************************************************************
+ QGLWidget UNIX/GLX-specific code
+ *****************************************************************************/
+void QGLWidget::init( QGLContext *context, const QGLWidget *shareWidget )
+{
+ qt_resolve_gl_symbols();
+
+ glcx = 0;
+ olw = 0;
+ autoSwap = TRUE;
+ if ( !context->device() )
+ context->setDevice( this );
+
+ if ( shareWidget )
+ setContext( context, shareWidget->context() );
+ else
+ setContext( context );
+ setBackgroundMode( NoBackground );
+
+ if ( isValid() && context->format().hasOverlay() ) {
+ QCString olwName( name() );
+ olwName += "-QGL_internal_overlay_widget";
+ olw = new QGLOverlayWidget( QGLFormat::defaultOverlayFormat(),
+ this, olwName, shareWidget );
+ if ( olw->isValid() ) {
+ olw->setAutoBufferSwap( FALSE );
+ olw->setFocusProxy( this );
+ }
+ else {
+ delete olw;
+ olw = 0;
+ glcx->glFormat.setOverlay( FALSE );
+ }
+ }
+}
+
+/*! \reimp */
+void QGLWidget::reparent( QWidget* parent, WFlags f, const QPoint& p,
+ bool showIt )
+{
+ if (glcx)
+ glcx->doneCurrent();
+ QWidget::reparent( parent, f, p, FALSE );
+ if ( showIt )
+ show();
+}
+
+
+void QGLWidget::setMouseTracking( bool enable )
+{
+ if ( olw )
+ olw->setMouseTracking( enable );
+ QWidget::setMouseTracking( enable );
+}
+
+
+void QGLWidget::resizeEvent( QResizeEvent * )
+{
+ if ( !isValid() )
+ return;
+ makeCurrent();
+ if ( !glcx->initialized() )
+ glInit();
+ glXWaitX();
+ resizeGL( width(), height() );
+ if ( olw )
+ olw->setGeometry( rect() );
+}
+
+const QGLContext* QGLWidget::overlayContext() const
+{
+ if ( olw )
+ return olw->context();
+ else
+ return 0;
+}
+
+
+void QGLWidget::makeOverlayCurrent()
+{
+ if ( olw )
+ olw->makeCurrent();
+}
+
+
+void QGLWidget::updateOverlayGL()
+{
+ if ( olw )
+ olw->updateGL();
+}
+
+void QGLWidget::setContext( QGLContext *context,
+ const QGLContext* shareContext,
+ bool deleteOldContext )
+{
+ if ( context == 0 ) {
+#if defined(QT_CHECK_NULL)
+ qWarning( "QGLWidget::setContext: Cannot set null context" );
+#endif
+ return;
+ }
+ if ( !context->deviceIsPixmap() && context->device() != this ) {
+#if defined(QT_CHECK_STATE)
+ qWarning( "QGLWidget::setContext: Context must refer to this widget" );
+#endif
+ return;
+ }
+
+ if ( glcx )
+ glcx->doneCurrent();
+ QGLContext* oldcx = glcx;
+ glcx = context;
+
+ bool createFailed = FALSE;
+ if ( !glcx->isValid() ) {
+ if ( !glcx->create( shareContext ? shareContext : oldcx ) )
+ createFailed = TRUE;
+ }
+ if ( createFailed ) {
+ if ( deleteOldContext )
+ delete oldcx;
+ return;
+ }
+
+ if ( glcx->windowCreated() || glcx->deviceIsPixmap() ) {
+ if ( deleteOldContext )
+ delete oldcx;
+ return;
+ }
+
+ bool visible = isVisible();
+ if ( visible )
+ hide();
+
+ XVisualInfo *vi = (XVisualInfo*)glcx->vi;
+ XSetWindowAttributes a;
+
+ a.colormap = choose_cmap( x11Display(), vi ); // find best colormap
+ a.background_pixel = backgroundColor().pixel( vi->screen );
+ a.border_pixel = black.pixel( vi->screen );
+ Window p = RootWindow( x11Display(), vi->screen );
+ if ( parentWidget() )
+ p = parentWidget()->winId();
+
+ Window w = XCreateWindow( x11Display(), p, x(), y(), width(), height(),
+ 0, vi->depth, InputOutput, vi->visual,
+ CWBackPixel|CWBorderPixel|CWColormap, &a );
+
+ Window *cmw;
+ Window *cmwret;
+ int count;
+ if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(),
+ &cmwret, &count ) ) {
+ cmw = new Window[count+1];
+ memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count );
+ XFree( (char *)cmwret );
+ int i;
+ for ( i=0; i<count; i++ ) {
+ if ( cmw[i] == winId() ) { // replace old window
+ cmw[i] = w;
+ break;
+ }
+ }
+ if ( i >= count ) // append new window
+ cmw[count++] = w;
+ } else {
+ count = 1;
+ cmw = new Window[count];
+ cmw[0] = w;
+ }
+
+#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
+ if ( oldcx && oldcx->windowCreated() )
+ glXReleaseBuffersMESA( x11Display(), winId() );
+#endif
+ if ( deleteOldContext )
+ delete oldcx;
+ oldcx = 0;
+
+ create( w );
+
+ XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw,
+ count );
+ delete [] cmw;
+
+ if ( visible )
+ show();
+ XFlush( x11Display() );
+ glcx->setWindowCreated( TRUE );
+}
+
+
+bool QGLWidget::renderCxPm( QPixmap* pm )
+{
+ if ( ((XVisualInfo*)glcx->vi)->depth != pm->depth() )
+ return FALSE;
+
+ GLXPixmap glPm;
+#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT)
+ glPm = glXCreateGLXPixmapMESA( x11Display(),
+ (XVisualInfo*)glcx->vi,
+ (Pixmap)pm->handle(),
+ choose_cmap( pm->x11Display(),
+ (XVisualInfo*)glcx->vi ) );
+#else
+ glPm = (Q_UINT32)glXCreateGLXPixmap( x11Display(),
+ (XVisualInfo*)glcx->vi,
+ (Pixmap)pm->handle() );
+#endif
+
+ if ( !glXMakeCurrent( x11Display(), glPm, (GLXContext)glcx->cx ) ) {
+ glXDestroyGLXPixmap( x11Display(), glPm );
+ return FALSE;
+ }
+
+ glDrawBuffer( GL_FRONT );
+ if ( !glcx->initialized() )
+ glInit();
+ resizeGL( pm->width(), pm->height() );
+ paintGL();
+ glFlush();
+ makeCurrent();
+ glXDestroyGLXPixmap( x11Display(), glPm );
+ resizeGL( width(), height() );
+ return TRUE;
+}
+
+const QGLColormap & QGLWidget::colormap() const
+{
+ return cmap;
+}
+
+/*\internal
+ Store color values in the given colormap.
+*/
+static void qStoreColors( QWidget * tlw, Colormap cmap,
+ const QGLColormap & cols )
+{
+ XColor c;
+ QRgb color;
+
+ for ( int i = 0; i < cols.size(); i++ ) {
+ color = cols.entryRgb( i );
+ c.pixel = i;
+ c.red = (ushort)( (qRed( color ) / 255.0) * 65535.0 + 0.5 );
+ c.green = (ushort)( (qGreen( color ) / 255.0) * 65535.0 + 0.5 );
+ c.blue = (ushort)( (qBlue( color ) / 255.0) * 65535.0 + 0.5 );
+ c.flags = DoRed | DoGreen | DoBlue;
+ XStoreColor( tlw->x11Display(), cmap, &c );
+ }
+}
+
+/*\internal
+ Check whether the given visual supports dynamic colormaps or not.
+*/
+static bool qCanAllocColors( QWidget * w )
+{
+ bool validVisual = FALSE;
+ int numVisuals;
+ long mask;
+ XVisualInfo templ;
+ XVisualInfo * visuals;
+ VisualID id = XVisualIDFromVisual( (Visual *)
+ w->topLevelWidget()->x11Visual() );
+
+ mask = VisualScreenMask;
+ templ.screen = w->x11Screen();
+ visuals = XGetVisualInfo( w->x11Display(), mask, &templ, &numVisuals );
+
+ for ( int i = 0; i < numVisuals; i++ ) {
+ if ( visuals[i].visualid == id ) {
+ switch ( visuals[i].c_class ) {
+ case TrueColor:
+ case StaticColor:
+ case StaticGray:
+ case GrayScale:
+ validVisual = FALSE;
+ break;
+ case DirectColor:
+ case PseudoColor:
+ validVisual = TRUE;
+ break;
+ }
+ break;
+ }
+ }
+ XFree( visuals );
+
+ if ( !validVisual )
+ return FALSE;
+ return TRUE;
+}
+
+void QGLWidget::setColormap( const QGLColormap & c )
+{
+ QWidget * tlw = topLevelWidget(); // must return a valid widget
+
+ cmap = c;
+ if ( !cmap.d )
+ return;
+
+ if ( !cmap.d->cmapHandle && !qCanAllocColors( this ) ) {
+ qWarning( "QGLWidget::setColormap: Cannot create a read/write "
+ "colormap for this visual" );
+ return;
+ }
+
+ // If the child GL widget is not of the same visual class as the
+ // toplevel widget we will get in trouble..
+ Window wid = tlw->winId();
+ Visual * vis = (Visual *) tlw->x11Visual();;
+ VisualID cvId = XVisualIDFromVisual( (Visual *) x11Visual() );
+ VisualID tvId = XVisualIDFromVisual( (Visual *) tlw->x11Visual() );
+ if ( cvId != tvId ) {
+ wid = winId();
+ vis = (Visual *) x11Visual();
+ }
+
+ if ( !cmap.d->cmapHandle ) // allocate a cmap if necessary
+ cmap.d->cmapHandle = XCreateColormap( x11Display(), wid, vis,
+ AllocAll );
+
+ qStoreColors( this, (Colormap) cmap.d->cmapHandle, c );
+ XSetWindowColormap( x11Display(), wid, (Colormap) cmap.d->cmapHandle );
+
+ // tell the wm that this window has a special colormap
+ Window * cmw;
+ Window * cmwret;
+ int count;
+ if ( XGetWMColormapWindows( x11Display(), tlw->winId(), &cmwret,
+ &count ) )
+ {
+ cmw = new Window[count+1];
+ memcpy( (char *) cmw, (char *) cmwret, sizeof(Window) * count );
+ XFree( (char *) cmwret );
+ int i;
+ for ( i = 0; i < count; i++ ) {
+ if ( cmw[i] == winId() ) {
+ break;
+ }
+ }
+ if ( i >= count ) // append new window only if not in the list
+ cmw[count++] = winId();
+ } else {
+ count = 1;
+ cmw = new Window[count];
+ cmw[0] = winId();
+ }
+ XSetWMColormapWindows( x11Display(), tlw->winId(), cmw, count );
+ delete [] cmw;
+}
+
+/*! \internal
+ Free up any allocated colormaps. This fn is only called for
+ top-level widgets.
+*/
+void QGLWidget::cleanupColormaps()
+{
+ if ( !cmap.d )
+ return;
+
+ if ( cmap.d->cmapHandle ) {
+ XFreeColormap( topLevelWidget()->x11Display(),
+ (Colormap) cmap.d->cmapHandle );
+ cmap.d->cmapHandle = 0;
+ }
+}
+
+void QGLWidget::macInternalFixBufferRect()
+{
+}
+
+#endif
diff --git a/src/opengl/qgl_x11_p.h b/src/opengl/qgl_x11_p.h
new file mode 100644
index 0000000..323fca1
--- /dev/null
+++ b/src/opengl/qgl_x11_p.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Definitions needed for resolving GL/GLX symbols using dlopen()
+** under X11.
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the OpenGL module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef QGL_P_H
+#define QGL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+//
+
+#ifdef QT_DLOPEN_OPENGL
+// resolve the GL symbols we use ourselves
+bool qt_resolve_gl_symbols(bool = TRUE);
+extern "C" {
+// GL symbols
+typedef void (*_glCallLists)( GLsizei n, GLenum type, const GLvoid *lists );
+typedef void (*_glClearColor)( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha );
+typedef void (*_glClearIndex)( GLfloat c );
+typedef void (*_glColor3ub)( GLubyte red, GLubyte green, GLubyte blue );
+typedef void (*_glDeleteLists)( GLuint list, GLsizei range );
+typedef void (*_glDrawBuffer)( GLenum mode );
+typedef void (*_glFlush)( void );
+typedef void (*_glIndexi)( GLint c );
+typedef void (*_glListBase)( GLuint base );
+typedef void (*_glLoadIdentity)( void );
+typedef void (*_glMatrixMode)( GLenum mode );
+typedef void (*_glOrtho)( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val );
+typedef void (*_glPopAttrib)( void );
+typedef void (*_glPopMatrix)( void );
+typedef void (*_glPushAttrib)( GLbitfield mask );
+typedef void (*_glPushMatrix)( void );
+typedef void (*_glRasterPos2i)( GLint x, GLint y );
+typedef void (*_glRasterPos3d)( GLdouble x, GLdouble y, GLdouble z );
+typedef void (*_glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels );
+typedef void (*_glViewport)( GLint x, GLint y, GLsizei width, GLsizei height );
+typedef void (*_glPixelStorei)( GLenum pname, GLint param );
+typedef void (*_glBitmap)( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap );
+typedef void (*_glDrawPixels)( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels );
+typedef void (*_glNewList)( GLuint list, GLenum mode );
+typedef void (*_glGetFloatv)( GLenum pname, GLfloat *params );
+typedef void (*_glGetIntegerv)( GLenum pname, GLint *params );
+typedef void (*_glEndList)( void );
+
+
+// GLX symbols - should be in the GL lib as well
+typedef XVisualInfo* (*_glXChooseVisual)(Display *dpy, int screen, int *attribList);
+typedef GLXContext (*_glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+typedef GLXPixmap (*_glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap);
+typedef void (*_glXDestroyContext)(Display *dpy, GLXContext ctx);
+typedef void (*_glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix);
+typedef const char* (*_glXGetClientString)(Display *dpy, int name );
+typedef int (*_glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value);
+typedef Bool (*_glXIsDirect)(Display *dpy, GLXContext ctx);
+typedef Bool (*_glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+typedef Bool (*_glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase);
+typedef const char* (*_glXQueryExtensionsString)(Display *dpy, int screen);
+typedef const char* (*_glXQueryServerString)(Display *dpy, int screen, int name);
+typedef void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable);
+typedef void (*_glXUseXFont)(Font font, int first, int count, int listBase);
+typedef void (*_glXWaitX)(void);
+
+extern _glCallLists qt_glCallLists;
+extern _glClearColor qt_glClearColor;
+extern _glClearIndex qt_glClearIndex;
+extern _glColor3ub qt_glColor3ub;
+extern _glDeleteLists qt_glDeleteLists;
+extern _glDrawBuffer qt_glDrawBuffer;
+extern _glFlush qt_glFlush;
+extern _glIndexi qt_glIndexi;
+extern _glListBase qt_glListBase;
+extern _glLoadIdentity qt_glLoadIdentity;
+extern _glMatrixMode qt_glMatrixMode;
+extern _glOrtho qt_glOrtho;
+extern _glPopAttrib qt_glPopAttrib;
+extern _glPopMatrix qt_glPopMatrix;
+extern _glPushAttrib qt_glPushAttrib;
+extern _glPushMatrix qt_glPushMatrix;
+extern _glRasterPos2i qt_glRasterPos2i;
+extern _glRasterPos3d qt_glRasterPos3d;
+extern _glReadPixels qt_glReadPixels;
+extern _glViewport qt_glViewport;
+extern _glPixelStorei qt_glPixelStorei;
+extern _glBitmap qt_glBitmap;
+extern _glDrawPixels qt_glDrawPixels;
+extern _glNewList qt_glNewList;
+extern _glGetFloatv qt_glGetFloatv;
+extern _glGetIntegerv qt_glGetIntegerv;
+extern _glEndList qt_glEndList;
+
+extern _glXChooseVisual qt_glXChooseVisual;
+extern _glXCreateContext qt_glXCreateContext;
+extern _glXCreateGLXPixmap qt_glXCreateGLXPixmap;
+extern _glXDestroyContext qt_glXDestroyContext;
+extern _glXDestroyGLXPixmap qt_glXDestroyGLXPixmap;
+extern _glXGetClientString qt_glXGetClientString;
+extern _glXGetConfig qt_glXGetConfig;
+extern _glXIsDirect qt_glXIsDirect;
+extern _glXMakeCurrent qt_glXMakeCurrent;
+extern _glXQueryExtension qt_glXQueryExtension;
+extern _glXQueryExtensionsString qt_glXQueryExtensionsString;
+extern _glXQueryServerString qt_glXQueryServerString;
+extern _glXSwapBuffers qt_glXSwapBuffers;
+extern _glXUseXFont qt_glXUseXFont;
+extern _glXWaitX qt_glXWaitX;
+}; // extern "C"
+
+#define glCallLists qt_glCallLists
+#define glClearColor qt_glClearColor
+#define glClearIndex qt_glClearIndex
+#define glColor3ub qt_glColor3ub
+#define glDeleteLists qt_glDeleteLists
+#define glDrawBuffer qt_glDrawBuffer
+#define glFlush qt_glFlush
+#define glIndexi qt_glIndexi
+#define glListBase qt_glListBase
+#define glLoadIdentity qt_glLoadIdentity
+#define glMatrixMode qt_glMatrixMode
+#define glOrtho qt_glOrtho
+#define glPopAttrib qt_glPopAttrib
+#define glPopMatrix qt_glPopMatrix
+#define glPushAttrib qt_glPushAttrib
+#define glPushMatrix qt_glPushMatrix
+#define glRasterPos2i qt_glRasterPos2i
+#define glRasterPos3d qt_glRasterPos3d
+#define glReadPixels qt_glReadPixels
+#define glViewport qt_glViewport
+#define glPixelStorei qt_glPixelStorei
+#define glBitmap qt_glBitmap
+#define glDrawPixels qt_glDrawPixels
+#define glNewList qt_glNewList
+#define glGetFloatv qt_glGetFloatv
+#define glGetIntegerv qt_glGetIntegerv
+#define glEndList qt_glEndList
+
+#define glXChooseVisual qt_glXChooseVisual
+#define glXCreateContext qt_glXCreateContext
+#define glXCreateGLXPixmap qt_glXCreateGLXPixmap
+#define glXDestroyContext qt_glXDestroyContext
+#define glXDestroyGLXPixmap qt_glXDestroyGLXPixmap
+#define glXGetClientString qt_glXGetClientString
+#define glXGetConfig qt_glXGetConfig
+#define glXIsDirect qt_glXIsDirect
+#define glXMakeCurrent qt_glXMakeCurrent
+#define glXQueryExtension qt_glXQueryExtension
+#define glXQueryExtensionsString qt_glXQueryExtensionsString
+#define glXQueryServerString qt_glXQueryServerString
+#define glXSwapBuffers qt_glXSwapBuffers
+#define glXUseXFont qt_glXUseXFont
+#define glXWaitX qt_glXWaitX
+
+#else
+inline bool qt_resolve_gl_symbols(bool = TRUE) { return TRUE; }
+#endif // QT_DLOPEN_OPENGL
+#endif // QGL_P_H
diff --git a/src/opengl/qglcolormap.cpp b/src/opengl/qglcolormap.cpp
new file mode 100644
index 0000000..2deb46b
--- /dev/null
+++ b/src/opengl/qglcolormap.cpp
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Implementation of QGLColormap class
+**
+** Created : 20010326
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+/*!
+ \class QGLColormap qglcolormap.h
+ \brief The QGLColormap class is used for installing custom colormaps into
+ QGLWidgets.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \module OpenGL
+ \ingroup graphics
+ \ingroup images
+
+ QGLColormap provides a platform independent way of specifying and
+ installing indexed colormaps into QGLWidgets. QGLColormap is
+ especially useful when using the \link opengl.html OpenGL\endlink
+ color-index mode.
+
+ Under X11 you must use an X server that supports either a \c
+ PseudoColor or \c DirectColor visual class. If your X server
+ currently only provides a \c GrayScale, \c TrueColor, \c
+ StaticColor or \c StaticGray visual, you will not be able to
+ allocate colorcells for writing. If this is the case, try setting
+ your X server to 8 bit mode. It should then provide you with at
+ least a \c PseudoColor visual. Note that you may experience
+ colormap flashing if your X server is running in 8 bit mode.
+
+ Under Windows the size of the colormap is always set to 256
+ colors. Note that under Windows you can also install colormaps
+ in child widgets.
+
+ This class uses explicit sharing (see \link shclass.html Shared
+ Classes\endlink).
+
+ Example of use:
+ \code
+ #include <qapplication.h>
+ #include <qglcolormap.h>
+
+ int main()
+ {
+ QApplication a( argc, argv );
+
+ MySuperGLWidget widget( 0 ); // A QGLWidget in color-index mode
+ QGLColormap colormap;
+
+ // This will fill the colormap with colors ranging from
+ // black to white.
+ for ( int i = 0; i < colormap.size(); i++ )
+ colormap.setEntry( i, qRgb( i, i, i ) );
+
+ widget.setColormap( colormap );
+ widget.show();
+ return a.exec();
+ }
+ \endcode
+
+ \sa QGLWidget::setColormap(), QGLWidget::colormap()
+*/
+
+#include "qglcolormap.h"
+#include "qmemarray.h"
+
+
+/*!
+ Construct a QGLColormap.
+*/
+QGLColormap::QGLColormap()
+{
+ d = 0;
+}
+
+
+/*!
+ Construct a shallow copy of \a map.
+*/
+QGLColormap::QGLColormap( const QGLColormap & map )
+{
+ d = map.d;
+ if ( d )
+ d->ref();
+}
+
+/*!
+ Dereferences the QGLColormap and deletes it if this was the last
+ reference to it.
+*/
+QGLColormap::~QGLColormap()
+{
+ if ( d && d->deref() ) {
+ delete d;
+ d = 0;
+ }
+}
+
+/*!
+ Assign a shallow copy of \a map to this QGLColormap.
+*/
+QGLColormap & QGLColormap::operator=( const QGLColormap & map )
+{
+ if ( map.d != 0 )
+ map.d->ref();
+
+ if ( d && d->deref() )
+ delete d;
+ d = map.d;
+
+ return *this;
+}
+
+/*!
+ Detaches this QGLColormap from the shared block.
+*/
+void QGLColormap::detach()
+{
+ if ( d && d->count != 1 ) {
+ // ### What about the actual colormap handle?
+ Private * newd = new Private();
+ newd->cells = d->cells;
+ newd->cells.detach();
+ if ( d->deref() )
+ delete d;
+ d = newd;
+ }
+}
+
+/*!
+ Set cell at index \a idx in the colormap to color \a color.
+*/
+void QGLColormap::setEntry( int idx, QRgb color )
+{
+ if ( !d )
+ d = new Private();
+
+#if defined(QT_CHECK_RANGE)
+ if ( idx < 0 || idx > (int) d->cells.size() ) {
+ qWarning( "QGLColormap::setRgb: Index out of range." );
+ return;
+ }
+#endif
+ d->cells[ idx ] = color;
+}
+
+/*!
+ Set an array of cells in this colormap. \a count is the number of
+ colors that should be set, \a colors is the array of colors, and
+ \a base is the starting index.
+*/
+void QGLColormap::setEntries( int count, const QRgb * colors, int base )
+{
+ if ( !d )
+ d = new Private();
+
+ if ( !colors || base < 0 || base >= (int) d->cells.size() )
+ return;
+
+ for( int i = base; i < base + count; i++ ) {
+ if ( i < (int) d->cells.size() )
+ setEntry( i, colors[i] );
+ else
+ break;
+ }
+}
+
+/*!
+ Returns the QRgb value in the colorcell with index \a idx.
+*/
+QRgb QGLColormap::entryRgb( int idx ) const
+{
+ if ( !d || idx < 0 || idx > (int) d->cells.size() )
+ return 0;
+ else
+ return d->cells[ idx ];
+}
+
+/*!
+ \overload
+
+ Set the cell with index \a idx in the colormap to color \a color.
+*/
+void QGLColormap::setEntry( int idx, const QColor & color )
+{
+ setEntry( idx, color.rgb() );
+}
+
+/*!
+ Returns the QRgb value in the colorcell with index \a idx.
+*/
+QColor QGLColormap::entryColor( int idx ) const
+{
+ if ( !d || idx < 0 || idx > (int) d->cells.size() )
+ return QColor();
+ else
+ return QColor( d->cells[ idx ] );
+}
+
+/*!
+ Returns TRUE if the colormap is empty; otherwise returns FALSE. A
+ colormap with no color values set is considered to be empty.
+*/
+bool QGLColormap::isEmpty() const
+{
+ return (d == 0) || (d->cells.size() == 0) || (d->cmapHandle == 0);
+}
+
+
+/*!
+ Returns the number of colorcells in the colormap.
+*/
+int QGLColormap::size() const
+{
+ return d != 0 ? d->cells.size() : 0;
+}
+
+/*!
+ Returns the index of the color \a color. If \a color is not in the
+ map, -1 is returned.
+*/
+int QGLColormap::find( QRgb color ) const
+{
+ if ( d )
+ return d->cells.find( color );
+ return -1;
+}
+
+/*!
+ Returns the index of the color that is the closest match to color
+ \a color.
+*/
+int QGLColormap::findNearest( QRgb color ) const
+{
+ int idx = find( color );
+ if ( idx >= 0 )
+ return idx;
+ int mapSize = size();
+ int mindist = 200000;
+ int r = qRed( color );
+ int g = qGreen( color );
+ int b = qBlue( color );
+ int rx, gx, bx, dist;
+ for ( int i=0; i < mapSize; i++ ) {
+ QRgb ci = d->cells[i];
+ rx = r - qRed( ci );
+ gx = g - qGreen( ci );
+ bx = b - qBlue( ci );
+ dist = rx*rx + gx*gx + bx*bx; // calculate distance
+ if ( dist < mindist ) { // minimal?
+ mindist = dist;
+ idx = i;
+ }
+ }
+ return idx;
+}
diff --git a/src/opengl/qglcolormap.h b/src/opengl/qglcolormap.h
new file mode 100644
index 0000000..d759058
--- /dev/null
+++ b/src/opengl/qglcolormap.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Definition of QGLColormap class
+**
+** Created : 20010326
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef QGLCOLORMAP_H
+#define QGLCOLORMAP_H
+
+#ifndef QT_H
+#include "qcolor.h"
+#include "qmemarray.h"
+#include "qshared.h"
+#endif // QT_H
+
+#if !defined( QT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL )
+#define QM_EXPORT_OPENGL
+#else
+#define QM_EXPORT_OPENGL Q_EXPORT
+#endif
+
+class QWidget;
+class QM_EXPORT_OPENGL QGLColormap
+{
+public:
+ QGLColormap();
+ QGLColormap( const QGLColormap & );
+ ~QGLColormap();
+
+ QGLColormap &operator=( const QGLColormap & );
+
+ bool isEmpty() const;
+ int size() const;
+ void detach();
+
+ void setEntries( int count, const QRgb * colors, int base = 0 );
+ void setEntry( int idx, QRgb color );
+ void setEntry( int idx, const QColor & color );
+ QRgb entryRgb( int idx ) const;
+ QColor entryColor( int idx ) const;
+ int find( QRgb color ) const;
+ int findNearest( QRgb color ) const;
+
+private:
+ class Private : public QShared
+ {
+ public:
+ Private() {
+ cells.resize( 256 ); // ### hardcoded to 256 entries for now
+ cmapHandle = 0;
+ }
+
+ ~Private() {
+ }
+
+ QMemArray<QRgb> cells;
+ Qt::HANDLE cmapHandle;
+ };
+
+ Private * d;
+
+ friend class QGLWidget;
+};
+
+#endif
diff --git a/src/opengl/qt_opengl.pri b/src/opengl/qt_opengl.pri
new file mode 100644
index 0000000..bb0a5d8
--- /dev/null
+++ b/src/opengl/qt_opengl.pri
@@ -0,0 +1,18 @@
+# Qt opengl module
+
+opengl {
+ HEADERS += $$OPENGL_H/qgl.h \
+ $$OPENGL_H/qglcolormap.h
+ SOURCES += $$OPENGL_CPP/qgl.cpp \
+ $$OPENGL_CPP/qglcolormap.cpp
+ x11 {
+ HEADERS += $$OPENGL_H/qgl_x11_p.h
+ SOURCES += $$OPENGL_CPP/qgl_x11.cpp
+ }
+ else:mac:SOURCES += $$OPENGL_CPP/qgl_mac.cpp
+ else:win32:SOURCES += $$OPENGL_CPP/qgl_win.cpp
+
+ dlopen_opengl:DEFINES+=QT_DLOPEN_OPENGL
+}
+
+