summaryrefslogtreecommitdiffstats
path: root/src/opengl/qgl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl/qgl.cpp')
-rw-r--r--src/opengl/qgl.cpp2367
1 files changed, 2367 insertions, 0 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
new file mode 100644
index 000000000..fd0d6815b
--- /dev/null
+++ b/src/opengl/qgl.cpp
@@ -0,0 +1,2367 @@
+/****************************************************************************
+**
+** Implementation of OpenGL classes for TQt
+**
+** Created : 970112
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the opengl module of the TQt 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 TQt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing retquirements 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.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** 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 TQGLFormat* qgl_default_format = 0;
+static TQGLFormat* 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 TQCleanupHandler<TQGLFormat> qgl_cleanup_format;
+
+
+/*!
+ \class TQGL qgl.h
+ \brief The TQGL class is a namespace for miscellaneous identifiers
+ in the TQt OpenGL module.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
+\endif
+
+ \module OpenGL
+ \ingroup graphics
+ \ingroup images
+
+
+ Normally you can ignore this class. TQGLWidget and the other
+ OpenGL<sup>*</sup> module classes inherit it, so when you make your
+ own TQGLWidget subclass you can use the identifiers in the TQGL
+ namespace without qualification.
+
+ However, you may occasionally find yourself in situations where you
+ need to refer to these identifiers from outside the TQGL namespace's
+ scope, e.g. in static functions. In such cases, simply write e.g. \c
+ TQGL::DoubleBuffer instead of just \c DoubleBuffer.
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+
+*/
+
+
+/*****************************************************************************
+ TQGLFormat implementation
+ *****************************************************************************/
+
+
+/*!
+ \class TQGLFormat qgl.h
+ \brief The TQGLFormat class specifies the display format of an OpenGL
+ rendering context.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">TQt 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 TQGLFormat 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 TQGLWidget, 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 TQGLFormat and make it the
+ default for the entire application:
+ \code
+ TQGLFormat f;
+ f.setAlpha( TRUE );
+ f.setStereo( TRUE );
+ TQGLFormat::setDefaultFormat( f );
+ \endcode
+
+ Or you can specify the desired format when creating an object of
+ your TQGLWidget subclass:
+ \code
+ TQGLFormat 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
+ TQGLFormat 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 retquired" );
+ }
+ }
+ \endcode
+
+ <sup>*</sup> OpenGL is a trademark of Silicon Graphics, Inc. in the
+ United States and other countries.
+
+ \sa TQGLContext, TQGLWidget
+*/
+
+
+/*!
+ Constructs a TQGLFormat 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
+*/
+
+TQGLFormat::TQGLFormat()
+{
+ opts = DoubleBuffer | DepthBuffer | Rgba | DirectRendering;
+ pln = 0;
+}
+
+
+/*!
+ Creates a TQGLFormat 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 TQGLWidget, for example:
+ \code
+ // The rendering in MyGLWidget depends on using
+ // stencil buffer and alpha channel
+ MyGLWidget::MyGLWidget( TQWidget* parent, const char* name )
+ : TQGLWidget( TQGLFormat( 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()
+*/
+
+TQGLFormat::TQGLFormat( int options, int plane )
+{
+ uint newOpts = options;
+ opts = defaultFormat().opts;
+ opts |= ( newOpts & 0xffff );
+ opts &= ~( newOpts >> 16 );
+ pln = plane;
+}
+
+
+/*!
+ \fn bool TQGLFormat::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(), TQGLContext::swapBuffers(),
+ TQGLWidget::swapBuffers()
+*/
+
+void TQGLFormat::setDoubleBuffer( bool enable )
+{
+ setOption( enable ? DoubleBuffer : SingleBuffer );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setDepth( bool enable )
+{
+ setOption( enable ? DepthBuffer : NoDepthBuffer );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setRgba( bool enable )
+{
+ setOption( enable ? Rgba : ColorIndex );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setAlpha( bool enable )
+{
+ setOption( enable ? AlphaChannel : NoAlphaChannel );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setAccum( bool enable )
+{
+ setOption( enable ? AccumBuffer : NoAccumBuffer );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setStencil( bool enable )
+{
+ setOption( enable ? StencilBuffer: NoStencilBuffer );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setStereo( bool enable )
+{
+ setOption( enable ? StereoBuffers : NoStereoBuffers );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLFormat::setDirectRendering( bool enable )
+{
+ setOption( enable ? DirectRendering : IndirectRendering );
+}
+
+
+/*!
+ \fn bool TQGLFormat::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 TQGLWidget to create an
+ additional context in an overlay plane. See the TQGLWidget
+ documentation for further information.
+
+ \sa hasOverlay()
+*/
+
+void TQGLFormat::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 TQGLFormat::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 TQGLWidget::isValid() invalid\endlink TQGLWidget will be
+ created.
+
+ \sa plane()
+*/
+void TQGLFormat::setPlane( int plane )
+{
+ pln = plane;
+}
+
+/*!
+ Sets the format option to \a opt.
+
+ \sa testOption()
+*/
+
+void TQGLFormat::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 TQGLFormat::testOption( FormatOption opt ) const
+{
+ if ( opt & 0xffff )
+ return ( opts & opt ) != 0;
+ else
+ return ( opts & ( opt >> 16 ) ) == 0;
+}
+
+
+
+/*!
+ \fn bool TQGLFormat::hasOpenGL()
+
+ Returns TRUE if the window system has any OpenGL support;
+ otherwise returns FALSE.
+
+ \warning This function must not be called until the TQApplication
+ object has been created.
+*/
+
+
+
+/*!
+ \fn bool TQGLFormat::hasOpenGLOverlays()
+
+ Returns TRUE if the window system supports OpenGL overlays;
+ otherwise returns FALSE.
+
+ \warning This function must not be called until the TQApplication
+ object has been created.
+*/
+
+/*!
+ Returns the default TQGLFormat for the application. All TQGLWidgets
+ 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 TQGLFormat().
+
+ \sa setDefaultFormat()
+*/
+
+TQGLFormat TQGLFormat::defaultFormat()
+{
+ if ( !qgl_default_format ) {
+ qgl_default_format = new TQGLFormat;
+ qgl_cleanup_format.add( &qgl_default_format );
+ }
+ return *qgl_default_format;
+}
+
+/*!
+ Sets a new default TQGLFormat 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
+ TQApplication a(argc, argv);
+ TQGLFormat f;
+ f.setDoubleBuffer( FALSE );
+ TQGLFormat::setDefaultFormat( f );
+ \endcode
+
+ \sa defaultFormat()
+*/
+
+void TQGLFormat::setDefaultFormat( const TQGLFormat &f )
+{
+ if ( !qgl_default_format ) {
+ qgl_default_format = new TQGLFormat;
+ qgl_cleanup_format.add( &qgl_default_format );
+ }
+ *qgl_default_format = f;
+}
+
+
+/*!
+ Returns the default TQGLFormat 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()
+*/
+
+TQGLFormat TQGLFormat::defaultOverlayFormat()
+{
+ if ( !qgl_default_overlay_format ) {
+ qgl_default_overlay_format = new TQGLFormat;
+ 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 TQGLFormat for overlay contexts to \a f. This
+ format is used whenever a TQGLWidget is created with a format that
+ hasOverlay() enabled.
+
+ For example, to get a double buffered overlay context (if
+ available), use code like this:
+
+ \code
+ TQGLFormat f = TQGLFormat::defaultOverlayFormat();
+ f.setDoubleBuffer( TRUE );
+ TQGLFormat::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( TQGLFormat( TQGL::HasOverlay ), ... );
+ if ( myWidget->format().hasOverlay() ) {
+ // Yes, we got an overlay, let's check _its_ format:
+ TQGLContext* 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 TQGLFormat::setDefaultOverlayFormat( const TQGLFormat &f )
+{
+ if ( !qgl_default_overlay_format ) {
+ qgl_default_overlay_format = new TQGLFormat;
+ 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 TQGLFormats are equal;
+ otherwise returns FALSE.
+*/
+
+bool operator==( const TQGLFormat& a, const TQGLFormat& b )
+{
+ return (a.opts == b.opts) && (a.pln == b.pln);
+}
+
+
+/*!
+ Returns FALSE if all the options of the two TQGLFormats are equal;
+ otherwise returns TRUE.
+*/
+
+bool operator!=( const TQGLFormat& a, const TQGLFormat& b )
+{
+ return !( a == b );
+}
+
+
+
+/*****************************************************************************
+ TQGLContext implementation
+ *****************************************************************************/
+
+TQGLContext* TQGLContext::currentCtx = 0;
+
+/*!
+ \class TQGLContext qgl.h
+ \brief The TQGLContext class encapsulates an OpenGL rendering context.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">TQt 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 TQGL::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 TQGLContext
+ 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 TQGLContext 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 TQGLContext 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()
+*/
+
+TQGLContext::TQGLContext( const TQGLFormat &format, TQPaintDevice *device )
+ : glFormat(format), reqFormat(format)
+{
+ init( device );
+}
+
+/*!
+ \overload
+ \internal
+*/
+TQGLContext::TQGLContext( const TQGLFormat &format )
+ : glFormat( format ), reqFormat(format)
+{
+ init();
+}
+
+/*!
+ Destroys the OpenGL context and frees its resources.
+*/
+
+TQGLContext::~TQGLContext()
+{
+ reset();
+ if ( d )
+ delete d;
+}
+
+
+/*!
+ \fn TQGLFormat TQGLContext::format() const
+
+ Returns the frame buffer format that was obtained (this may be a
+ subset of what was requested).
+
+ \sa requestedFormat()
+*/
+
+/*!
+ \fn TQGLFormat TQGLContext::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
+ TQGLContext *cx;
+ // ...
+ TQGLFormat 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 TQGLContext::setFormat( const TQGLFormat &format )
+{
+ reset();
+ glFormat = reqFormat = format;
+}
+
+/*!
+ \internal
+*/
+void TQGLContext::setDevice( TQPaintDevice *pDev )
+{
+ if ( isValid() )
+ reset();
+ d->paintDevice = pDev;
+ if ( d->paintDevice && (d->paintDevice->devType() != TQInternal::Widget
+ && d->paintDevice->devType() != TQInternal::Pixmap) ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "TQGLContext: Unsupported paint device type" );
+#endif
+ }
+}
+
+void TQGLContext::init( TQPaintDevice *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 = TQRect(1, 1, 1, 1);
+#endif
+ d->crWin = FALSE;
+ d->initDone = FALSE;
+ d->sharing = FALSE;
+}
+
+/*!
+ \fn bool TQGLContext::isValid() const
+
+ Returns TRUE if a GL rendering context has been successfully
+ created; otherwise returns FALSE.
+*/
+
+/*!
+ \fn void TQGLContext::setValid( bool valid )
+ \internal
+
+ Forces the GL rendering context to be valid.
+*/
+
+/*!
+ \fn bool TQGLContext::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 TQGLContext::deviceIsPixmap() const
+
+ Returns TRUE if the paint device of this context is a pixmap;
+ otherwise returns FALSE.
+*/
+
+/*!
+ \fn bool TQGLContext::windowCreated() const
+
+ Returns TRUE if a window has been created for this context;
+ otherwise returns FALSE.
+
+ \sa setWindowCreated()
+*/
+
+/*!
+ \fn void TQGLContext::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 TQGLContext::colorIndex( const TQColor& c ) const
+
+ \internal
+
+ Returns a colormap index for the color c, in ColorIndex mode. Used
+ by qglColor() and qglClearColor().
+*/
+
+
+/*!
+ \fn bool TQGLContext::initialized() const
+
+ Returns TRUE if this context has been initialized, i.e. if
+ TQGLWidget::initializeGL() has been performed on it; otherwise
+ returns FALSE.
+
+ \sa setInitialized()
+*/
+
+/*!
+ \fn void TQGLContext::setInitialized( bool on )
+
+ If \a on is TRUE the context has been initialized, i.e.
+ TQGLContext::setInitialized() has been called on it. If \a on is
+ FALSE the context has not been initialized.
+
+ \sa initialized()
+*/
+
+/*!
+ \fn const TQGLContext* TQGLContext::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 TQColor TQGLContext::overlayTransparentColor() const
+
+ If this context is a valid context in an overlay plane, returns
+ the plane's transparent color. Otherwise returns an \link
+ TQColor::isValid() invalid \endlink color.
+
+ The returned color's \link TQColor::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 TQColor object will generally work as expected only
+ when passed as the argument to TQGLWidget::qglColor() or
+ TQGLWidget::qglClearColor(). Under certain circumstances it can
+ also be used to draw transparent graphics with a TQPainter. 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 TQGLContext, 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. TQGLContext
+ 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 TQGLContext::create( const TQGLContext* shareContext )
+{
+ reset();
+ d->valid = chooseContext( shareContext );
+ return d->valid;
+}
+
+
+
+/*!
+ \fn bool TQGLContext::chooseContext( const TQGLContext* 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 TQGLContext::reset()
+
+ Resets the context and makes it invalid.
+
+ \sa create(), isValid()
+*/
+
+
+/*!
+ \fn void TQGLContext::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 TQGLContext::swapBuffers() const
+
+ Swaps the screen contents with an off-screen buffer. Only works if
+ the context is in double buffer mode.
+
+ \sa TQGLFormat::setDoubleBuffer()
+*/
+
+
+/*!
+ \fn void TQGLContext::doneCurrent()
+
+ Makes no GL context the current context. Normally, you do not need
+ to call this function; TQGLContext calls it as necessary.
+*/
+
+
+/*!
+ \fn TQPaintDevice* TQGLContext::device() const
+
+ Returns the paint device set for this context.
+
+ \sa TQGLContext::TQGLContext()
+*/
+
+/*!
+ \fn void TQGLContext::generateFontDisplayLists( const TQFont& 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 TQGLWidget::renderText()
+*/
+
+
+/*****************************************************************************
+ TQGLWidget implementation
+ *****************************************************************************/
+
+
+/*!
+ \class TQGLWidget qgl.h
+ \brief The TQGLWidget class is a widget for rendering OpenGL graphics.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">TQt Enterprise Edition</a>.
+\endif
+
+ \ingroup graphics
+ \ingroup images
+ \mainclass
+ \module OpenGL
+
+ TQGLWidget provides functionality for displaying OpenGL<sup>*</sup>
+ graphics integrated into a TQt application. It is very simple to
+ use. You inherit from it and use the subclass like any other
+ TQWidget, except that instead of drawing the widget's contents
+ using TQPainter etc. you use the standard OpenGL rendering
+ commands.
+
+ TQGLWidget 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 TQGLWidget subclass might look:
+
+ \code
+ class MyGLDrawer : public TQGLWidget
+ {
+ Q_OBJECT // must include this if you use TQt signals/slots
+
+ public:
+ MyGLDrawer( TQWidget *parent, const char *name )
+ : TQGLWidget(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 TQTimer 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.
+
+ TQGLWidget provides functions for requesting a new display \link
+ TQGLFormat format\endlink and you can also create widgets with
+ customized rendering \link TQGLContext contexts\endlink.
+
+ You can also share OpenGL display lists between TQGLWidgets (see
+ the documentation of the TQGLWidget constructors for details).
+
+ \section1 Overlays
+
+ The TQGLWidget 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 TQGLFormat
+ format\endlink. (Note: Overlay must be requested in the format
+ passed to the TQGLWidget 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 TQt 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 TQGLWidgetPrivate
+{
+public:
+ TQMap<TQString, int> displayListCache;
+};
+
+static TQPtrDict<TQGLWidgetPrivate> * qgl_d_ptr = 0;
+static TQSingleCleanupHandler< TQPtrDict<TQGLWidgetPrivate> > qgl_cleanup_d_ptr;
+
+static TQGLWidgetPrivate * qgl_d( const TQGLWidget * w )
+{
+ if ( !qgl_d_ptr ) {
+ qgl_d_ptr = new TQPtrDict<TQGLWidgetPrivate>;
+ qgl_cleanup_d_ptr.set( &qgl_d_ptr );
+ qgl_d_ptr->setAutoDelete( TRUE );
+ }
+ TQGLWidgetPrivate * ret = qgl_d_ptr->find( (void *) w );
+ if ( !ret ) {
+ ret = new TQGLWidgetPrivate;
+ qgl_d_ptr->replace( (void *) w, ret );
+ }
+ return ret;
+}
+
+void qgl_delete_d( const TQGLWidget * 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 TQGLFormat::defaultFormat() default format\endlink is
+ used. The widget will be \link isValid() invalid\endlink if the
+ system has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the TQWidget constructor.
+
+ If the \a shareWidget parameter points to a valid TQGLWidget, 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 TQGLWidget subclass.
+
+ \sa TQGLFormat::defaultFormat()
+*/
+
+TQGLWidget::TQGLWidget( TQWidget *parent, const char *name,
+ const TQGLWidget* shareWidget, WFlags f )
+ : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
+{
+ init( new TQGLContext(TQGLFormat::defaultFormat(), this), shareWidget );
+}
+
+
+/*!
+ Constructs an OpenGL widget with parent \a parent, called \a name.
+
+ The \a format argument specifies the desired \link TQGLFormat
+ 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 TQGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the TQWidget constructor.
+
+ If the \a shareWidget parameter points to a valid TQGLWidget, 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 TQGLWidget subclass.
+
+ \sa TQGLFormat::defaultFormat(), isValid()
+*/
+
+TQGLWidget::TQGLWidget( const TQGLFormat &format, TQWidget *parent,
+ const char *name, const TQGLWidget* shareWidget,
+ WFlags f )
+ : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
+{
+ init( new TQGLContext(format, this), shareWidget );
+}
+
+/*!
+ Constructs an OpenGL widget with parent \a parent, called \a name.
+
+ The \a context argument is a pointer to the TQGLContext that
+ you wish to be bound to this widget. This allows you to pass in
+ your own TQGLContext sub-classes.
+
+ The widget will be \link isValid() invalid\endlink if the system
+ has no \link TQGLFormat::hasOpenGL() OpenGL support\endlink.
+
+ The \a parent, \a name and widget flag, \a f, arguments are passed
+ to the TQWidget constructor.
+
+ If the \a shareWidget parameter points to a valid TQGLWidget, 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 TQGLWidget subclass.
+
+ \sa TQGLFormat::defaultFormat(), isValid()
+*/
+TQGLWidget::TQGLWidget( TQGLContext *context, TQWidget *parent,
+ const char *name, const TQGLWidget *shareWidget, WFlags f )
+ : TQWidget( parent, name, f | TQt::WWinOwnDC | TQt::WNoAutoErase )
+{
+ init( context, shareWidget );
+}
+
+/*!
+ Destroys the widget.
+*/
+
+TQGLWidget::~TQGLWidget()
+{
+#if defined(GLX_MESA_release_buffers) && defined(TQGL_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(TQGL_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 TQGLFormat TQGLWidget::format() const
+
+ Returns the format of the contained GL rendering context.
+*/
+
+/*!
+ \fn bool TQGLWidget::doubleBuffer() const
+
+ Returns TRUE if the contained GL rendering context has double
+ buffering; otherwise returns FALSE.
+
+ \sa TQGLFormat::doubleBuffer()
+*/
+
+/*!
+ \fn void TQGLWidget::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 TQGLWidget::autoBufferSwap() const
+
+ Returns TRUE if the widget is doing automatic GL buffer swapping;
+ otherwise returns FALSE.
+
+ \sa setAutoBufferSwap()
+*/
+
+/*!
+ \fn bool TQGLWidget::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 TQGLFormat::hasOpenGL() OpenGL support\endlink.
+*/
+
+bool TQGLWidget::isValid() const
+{
+ return glcx->isValid();
+}
+
+/*!
+ \fn bool TQGLWidget::isSharing() const
+
+ Returns TRUE if display list sharing with another TQGLWidget 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 TQGLWidgets use different
+ formats.
+
+ \sa format()
+*/
+
+bool TQGLWidget::isSharing() const
+{
+ return glcx->isSharing();
+}
+
+/*!
+ \fn void TQGLWidget::makeCurrent()
+
+ Makes this widget the current widget for OpenGL operations, i.e.
+ makes the widget's rendering context the current OpenGL rendering
+ context.
+*/
+
+void TQGLWidget::makeCurrent()
+{
+#if defined( Q_WS_MAC )
+ macInternalDoubleBuffer(); //make sure the correct context is used
+#endif
+ glcx->makeCurrent();
+}
+
+/*!
+ \fn void TQGLWidget::doneCurrent()
+
+ Makes no GL context the current context. Normally, you do not need
+ to call this function; TQGLContext calls it as necessary. However,
+ it may be useful in multithreaded environments.
+*/
+
+void TQGLWidget::doneCurrent()
+{
+ glcx->doneCurrent();
+}
+
+/*!
+ \fn void TQGLWidget::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(), TQGLFormat::setDoubleBuffer()
+*/
+
+void TQGLWidget::swapBuffers()
+{
+ glcx->swapBuffers();
+#if defined(Q_WS_MAC)
+ if(macInternalDoubleBuffer() && gl_pix)
+ bitBlt(this, 0, 0, gl_pix);
+#endif
+}
+
+
+/*!
+ \fn const TQGLContext* TQGLWidget::overlayContext() const
+
+ Returns the overlay context of this widget, or 0 if this widget
+ has no overlay.
+
+ \sa context()
+*/
+
+
+
+/*!
+ \fn void TQGLWidget::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 TQGLContext, 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 TQGLWidgets, but it may fail. Use isSharing() to test.
+
+ \sa format(), isSharing(), isValid()
+*/
+
+void TQGLWidget::setFormat( const TQGLFormat &format )
+{
+ setContext( new TQGLContext(format,this) );
+}
+
+
+
+
+/*!
+ \fn const TQGLContext *TQGLWidget::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 TQGLWidget::setContext( TQGLContext *context,
+ const TQGLContext* shareContext,
+ bool deleteOldContext )
+
+ Sets a new context for this widget. The TQGLContext \a context must
+ be created using \e new. TQGLWidget will delete \a context when
+ another context is set or when the widget is destroyed.
+
+ If \a context is invalid, TQGLContext::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 TQGLWidgets 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 TQGLWidget::updateGL()
+
+ Updates the widget by calling glDraw().
+*/
+
+void TQGLWidget::updateGL()
+{
+ glDraw();
+}
+
+
+/*!
+ \fn void TQGLWidget::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 TQGLContext. Reimplement it in a subclass.
+
+ This function should set up any retquired 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 TQGLWidget::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 TQGLWidget::paintGL()
+{
+}
+
+
+/*!
+ \fn void TQGLWidget::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 TQGLWidget::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 retquired 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 TQGLWidget::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 TQGLWidget::paintOverlayGL()
+{
+}
+
+
+/*!
+ \fn void TQGLWidget::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 TQGLWidget::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 TQGLWidget::paintEvent( TQPaintEvent * )
+{
+ glDraw();
+ updateOverlayGL();
+}
+
+
+/*!
+ \fn void TQGLWidget::resizeEvent( TQResizeEvent * )
+
+ Handles resize events. Calls the virtual function resizeGL().
+*/
+
+
+/*!
+ \fn void TQGLWidget::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 TQGLWidgets.
+
+ This method will create a pixmap and a temporary TQGLContext 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 TQGLContext will not be initialized
+ properly, and the rendered pixmap may be incomplete/corrupted.
+*/
+
+TQPixmap TQGLWidget::renderPixmap( int w, int h, bool useContext )
+{
+ TQSize sz = size();
+ if ( (w > 0) && (h > 0) )
+ sz = TQSize( w, h );
+
+#if defined(Q_WS_X11)
+ TQPixmap pm( sz.width(), sz.height(), x11Depth() );
+ bool needConversion = x11Visual() != TQPaintDevice::x11AppVisual();
+
+ // make sure the pixmap uses the same visual as the widget itself
+ if ( needConversion ) {
+ TQPaintDeviceX11Data* xd = pm.getX11Data( TRUE );
+ xd->x_depth = x11Depth();
+ xd->x_visual = (Visual *) x11Visual();
+ pm.setX11Data( xd );
+ }
+#else
+ TQPixmap pm;
+ pm.resize( sz );
+#endif
+
+ glcx->doneCurrent();
+
+ bool success = TRUE;
+
+ if ( useContext && isValid() && renderCxPm( &pm ) )
+ return pm;
+
+ TQGLFormat fmt = glcx->requestedFormat();
+ fmt.setDirectRendering( FALSE ); // Direct is unlikely to work
+ fmt.setDoubleBuffer( FALSE ); // We don't need dbl buf
+
+ TQGLContext* ocx = glcx;
+ bool wasCurrent = (TQGLContext::currentContext() == ocx );
+ ocx->doneCurrent();
+ glcx = new TQGLContext( 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 ) {
+ TQImage image = pm.convertToImage();
+ TQPixmap p;
+ p = image;
+ return p;
+ }
+#endif
+ return pm;
+ } else
+ return TQPixmap();
+}
+
+
+
+/*!
+ 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.
+*/
+TQImage TQGLWidget::grabFrameBuffer( bool withAlpha )
+{
+#if defined( Q_WS_MAC )
+ if(dblbuf == macInternalDoubleBuffer(FALSE) && gl_pix) //why not optimize?
+ return ((TQPixmap*)gl_pix)->convertToImage();
+#endif
+ makeCurrent();
+ TQImage res;
+ int w = width();
+ int h = height();
+ if ( format().rgba() ) {
+ res = TQImage( w, h, 32 );
+ glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, res.bits() );
+ if ( TQImage::systemByteOrder() == TQImage::BigEndian ) {
+ // OpenGL gives RGBA; TQt 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); TQt wants ARGB
+ res = res.swapRGB();
+ }
+ res.setAlphaBuffer( withAlpha && format().alpha() );
+ }
+ else {
+#if defined (Q_WS_WIN)
+ res = TQImage( w, h, 8 );
+ glReadPixels( 0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
+ res.bits() );
+ int palSize = 0;
+ const TQRgb* pal = TQColor::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 TQGLWidget::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 TQGLWidget::glDraw()
+{
+ if ( !isValid() )
+ return;
+ makeCurrent();
+ if ( glcx->deviceIsPixmap() )
+ glDrawBuffer( GL_FRONT );
+ if ( !glcx->initialized() ) {
+ glInit();
+ TQPaintDeviceMetrics 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(), TQGLContext::currentContext(), TQColor
+*/
+
+void TQGLWidget::qglColor( const TQColor& c ) const
+{
+ const TQGLContext* ctx = TQGLContext::currentContext();
+ if ( ctx ) {
+ if ( ctx->format().rgba() )
+ glColor3ub( c.red(), c.green(), c.blue() );
+
+ else if ( ctx->device() == context()->device()
+ && !cmap.isEmpty() ) { // TQGLColormap 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(), TQGLContext::currentContext(), TQColor
+*/
+
+void TQGLWidget::qglClearColor( const TQColor& c ) const
+{
+ const TQGLContext* ctx = TQGLContext::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() ) { // TQGLColormap 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 TQImage, but TQImage::width(), TQImage::height() and
+ TQImage::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.
+*/
+
+
+TQImage TQGLWidget::convertToGLFormat( const TQImage& img )
+{
+ TQImage res = img.convertDepth( 32 );
+ res = res.mirror();
+
+ if ( TQImage::systemByteOrder() == TQImage::BigEndian ) {
+ // TQt 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 {
+ // TQt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards)
+ res = res.swapRGB();
+ }
+ return res;
+}
+
+
+/*!
+ \fn TQGLColormap & TQGLWidget::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 TQColormap
+ returned will be empty.
+
+ \sa setColormap()
+*/
+
+/*!
+ \fn void TQGLWidget::setColormap( const TQGLColormap & 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 TQGLWidget::displayListBase( const TQFont & fnt, int listBase )
+{
+ int base;
+
+ TQGLWidgetPrivate * 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
+ TQString color_key;
+ if (fnt.styleStrategy() != TQFont::NoAntialias) {
+ GLfloat color[4];
+ glGetFloatv(GL_CURRENT_COLOR, color);
+ color_key.sprintf("%f_%f_%f",color[0], color[1], color[2]);
+ }
+ TQString key = fnt.key() + color_key + TQString::number((int) regenerate);
+#else
+ TQString key = fnt.key() + TQString::number((int) regenerate);
+#endif
+
+ if ( !regenerate && (d->displayListCache.find( key ) != d->displayListCache.end()) ) {
+ base = d->displayListCache[ key ];
+ } else {
+ int maxBase = listBase - 256;
+ TQMapConstIterator<TQString,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 TQGLWidget::renderText( int x, int y, const TQString & str, const TQFont & 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 TQGLWidget::renderText( double x, double y, double z, const TQString & str, const TQFont & 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();
+}
+
+/*****************************************************************************
+ TQGL classes overview documentation.
+ *****************************************************************************/
+
+/*!
+
+\page opengl.html
+
+\title TQt OpenGL 3D Graphics
+
+\if defined(commercial)
+This module is part of the \link commercialeditions.html TQt 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 TQt on \e both platforms.
+
+The TQt OpenGL module makes it easy to use OpenGL in TQt applications.
+It provides an OpenGL widget class that can be used just like any
+other TQt widget, except that it opens an OpenGL display buffer where
+you can use the OpenGL API to render the contents.
+
+The TQt OpenGL module is implemented as a platform-independent TQt/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 TQt API.
+
+\section1 Installation
+
+When you install TQt for X11, the configure script will autodetect if
+OpenGL headers and libraries are installed on your system, and if so,
+it will include the TQt OpenGL module in the TQt 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 retquire threading to be enabled for OpenGL, so if
+OpenGL is not detected, try \c{configure -thread}.
+
+When you install TQt for Windows, the TQt OpenGL module is always
+included.
+
+The TQt OpenGL module is not licensed for use with the TQt Professional
+Edition. Consider upgrading to the TQt Enterprise Edition if you
+retquire 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 TQGL Classes
+
+The OpenGL support classes in TQt are:
+\list
+\i \link TQGLWidget TQGLWidget\endlink: An easy-to-use TQt
+ widget for rendering OpenGL scenes.
+\i \link TQGLContext TQGLContext\endlink: Encapsulates an OpenGL rendering context.
+\i \link TQGLFormat TQGLFormat\endlink: Specifies the
+display format of a rendering context.
+\i \link TQGLColormap TQGLColormap\endlink: Handles indexed
+colormaps in GL-index mode.
+\endlist
+
+Many applications only need the high-level TQGLWidget class. The other
+TQGL 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 TQGL 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 TQGL::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
+*/