You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2368 lines
66 KiB
2368 lines
66 KiB
/****************************************************************************
|
|
**
|
|
** 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 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.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 "ntqgl.h"
|
|
#include "ntqpixmap.h"
|
|
#include "ntqpaintdevicemetrics.h"
|
|
#include "ntqimage.h"
|
|
#include "ntqcleanuphandler.h"
|
|
#include "ntqptrdict.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 ntqgl.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 ntqgl.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() ) {
|
|
tqFatal( "Cool hardware required" );
|
|
}
|
|
}
|
|
\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() )
|
|
tqWarning( "Could not get stencil buffer; results will be suboptimal" );
|
|
if ( !format().alphaChannel() )
|
|
tqWarning( "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 ntqgl.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)
|
|
tqWarning( "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 ntqgl.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
|
|
{
|
|
TQ_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 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 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 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 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( tqstrlen(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( tqstrlen(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 require 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
|
|
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 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
|
|
*/
|