From 1e9fa8e06de5da7fcc268e9cccb2d6b21c5f53a3 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sat, 20 Jul 2024 20:15:52 +0900 Subject: Rename graphics class nt* related files to equivalent tq* (part 2) Signed-off-by: Michele Calgaro --- src/opengl/ntqgl.h | 541 ---------- src/opengl/ntqglcolormap.h | 99 -- src/opengl/qgl.cpp | 2367 ------------------------------------------- src/opengl/qgl_x11.cpp | 1406 ------------------------- src/opengl/qgl_x11_p.h | 197 ---- src/opengl/qglcolormap.cpp | 292 ------ src/opengl/qt_opengl.pri | 12 +- src/opengl/tqgl.cpp | 2367 +++++++++++++++++++++++++++++++++++++++++++ src/opengl/tqgl.h | 541 ++++++++++ src/opengl/tqgl_x11.cpp | 1406 +++++++++++++++++++++++++ src/opengl/tqgl_x11_p.h | 197 ++++ src/opengl/tqglcolormap.cpp | 292 ++++++ src/opengl/tqglcolormap.h | 99 ++ 13 files changed, 4908 insertions(+), 4908 deletions(-) delete mode 100644 src/opengl/ntqgl.h delete mode 100644 src/opengl/ntqglcolormap.h delete mode 100644 src/opengl/qgl.cpp delete mode 100644 src/opengl/qgl_x11.cpp delete mode 100644 src/opengl/qgl_x11_p.h delete mode 100644 src/opengl/qglcolormap.cpp create mode 100644 src/opengl/tqgl.cpp create mode 100644 src/opengl/tqgl.h create mode 100644 src/opengl/tqgl_x11.cpp create mode 100644 src/opengl/tqgl_x11_p.h create mode 100644 src/opengl/tqglcolormap.cpp create mode 100644 src/opengl/tqglcolormap.h (limited to 'src/opengl') diff --git a/src/opengl/ntqgl.h b/src/opengl/ntqgl.h deleted file mode 100644 index 86eeddf6e..000000000 --- a/src/opengl/ntqgl.h +++ /dev/null @@ -1,541 +0,0 @@ -/**************************************************************************** -** -** Definition 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. -** -**********************************************************************/ - -#ifndef TQGL_H -#define TQGL_H - -#ifndef QT_H -#include "tqwidget.h" -#include "ntqglcolormap.h" -#endif // QT_H - -#if !defined( TQT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL ) -#define TQM_EXPORT_OPENGL -#else -#define TQM_EXPORT_OPENGL TQ_EXPORT -#endif - -#ifndef TQT_NO_COMPAT -#define TQGL_VERSION 450 -#define TQGL_VERSION_STR "4.5" -TQM_EXPORT_OPENGL inline const char *qGLVersion() { - tqObsolete( 0, "qGLVersion", "qVersion" ); - return TQGL_VERSION_STR; -} -#endif - -#if defined(TQ_WS_WIN) -# include "qt_windows.h" -#endif - -#if defined(TQ_WS_MAC) -#if !defined( TQMAC_OPENGL_DOUBLEBUFFER ) -/* This macro is different now. If the macro is not defined TQGLWidget will - * try to determine when you need double buffering. If set to 0 it will - * never double buffer and *can* be acclerated. If set to 1 (the default) - * it will always double buffer. Unlike before the value of this macro does - * not upset binary compatability either. */ -#if QT_MACOSX_VERSION >= 0x1020 -# define TQMAC_OPENGL_DOUBLEBUFFER 0 -#endif -#endif -# include -# include -#else -# include -# include -#endif - -#if defined(TQ_WS_WIN) || defined(TQ_WS_MAC) -class TQGLCmap; -#endif - -class TQPixmap; -#if defined(TQ_WS_X11) -class TQGLOverlayWidget; -#endif - -// Namespace class: -class TQM_EXPORT_OPENGL TQGL -{ -public: - enum FormatOption { - DoubleBuffer = 0x0001, - DepthBuffer = 0x0002, - Rgba = 0x0004, - AlphaChannel = 0x0008, - AccumBuffer = 0x0010, - StencilBuffer = 0x0020, - StereoBuffers = 0x0040, - DirectRendering = 0x0080, - HasOverlay = 0x0100, - SingleBuffer = DoubleBuffer << 16, - NoDepthBuffer = DepthBuffer << 16, - ColorIndex = Rgba << 16, - NoAlphaChannel = AlphaChannel << 16, - NoAccumBuffer = AccumBuffer << 16, - NoStencilBuffer = StencilBuffer << 16, - NoStereoBuffers = StereoBuffers << 16, - IndirectRendering = DirectRendering << 16, - NoOverlay = HasOverlay << 16 - }; -}; - - - -class TQM_EXPORT_OPENGL TQGLFormat : public TQGL -{ -public: - TQGLFormat(); - TQGLFormat( int options, int plane = 0 ); - - bool doubleBuffer() const; - void setDoubleBuffer( bool enable ); - bool depth() const; - void setDepth( bool enable ); - bool rgba() const; - void setRgba( bool enable ); - bool alpha() const; - void setAlpha( bool enable ); - bool accum() const; - void setAccum( bool enable ); - bool stencil() const; - void setStencil( bool enable ); - bool stereo() const; - void setStereo( bool enable ); - bool directRendering() const; - void setDirectRendering( bool enable ); - bool hasOverlay() const; - void setOverlay( bool enable ); - - int plane() const; - void setPlane( int plane ); - - void setOption( FormatOption opt ); - bool testOption( FormatOption opt ) const; - - static TQGLFormat defaultFormat(); - static void setDefaultFormat( const TQGLFormat& f ); - - static TQGLFormat defaultOverlayFormat(); - static void setDefaultOverlayFormat( const TQGLFormat& f ); - - static bool hasOpenGL(); - static bool hasOpenGLOverlays(); - - friend TQM_EXPORT_OPENGL bool operator==( const TQGLFormat&, - const TQGLFormat& ); - friend TQM_EXPORT_OPENGL bool operator!=( const TQGLFormat&, - const TQGLFormat& ); -private: - uint opts; - int pln; -}; - - -TQM_EXPORT_OPENGL bool operator==( const TQGLFormat&, const TQGLFormat& ); -TQM_EXPORT_OPENGL bool operator!=( const TQGLFormat&, const TQGLFormat& ); - -class TQM_EXPORT_OPENGL TQGLContext : public TQGL -{ -public: - TQGLContext( const TQGLFormat& format, TQPaintDevice* device ); - TQGLContext( const TQGLFormat& format ); - virtual ~TQGLContext(); - - virtual bool create( const TQGLContext* shareContext = 0 ); - bool isValid() const; - bool isSharing() const; - virtual void reset(); - - TQGLFormat format() const; - TQGLFormat requestedFormat() const; - virtual void setFormat( const TQGLFormat& format ); - - virtual void makeCurrent(); - virtual void swapBuffers() const; - - TQPaintDevice* device() const; - - TQColor overlayTransparentColor() const; - - static const TQGLContext* currentContext(); - -protected: - virtual bool chooseContext( const TQGLContext* shareContext = 0 ); - virtual void doneCurrent(); // ### 4.0: make this public - needed for multithreading stuff - -#if defined(TQ_WS_WIN) - virtual int choosePixelFormat( void* pfd, HDC pdc ); -#endif -#if defined(TQ_WS_X11) - virtual void* tryVisual( const TQGLFormat& f, int bufDepth = 1 ); - virtual void* chooseVisual(); -#endif -#if defined(TQ_WS_MAC) - virtual void* chooseMacVisual(GDHandle); -#endif - - bool deviceIsPixmap() const; - bool windowCreated() const; - void setWindowCreated( bool on ); - bool initialized() const; - void setInitialized( bool on ); - void generateFontDisplayLists( const TQFont & fnt, int listBase ); - - uint colorIndex( const TQColor& c ) const; - void setValid( bool valid ); - void setDevice( TQPaintDevice *pDev ); - -protected: -#if defined(TQ_WS_WIN) - HGLRC rc; - HDC dc; - WId win; - int pixelFormatId; - TQGLCmap* cmap; -#elif defined(TQ_WS_X11) || defined(TQ_WS_MAC) - void* vi; - void* cx; -#if defined(TQ_WS_X11) - TQ_UINT32 gpm; -#endif -#endif - TQGLFormat glFormat; - TQGLFormat reqFormat; - static TQGLContext* currentCtx; - -private: - void init( TQPaintDevice *dev = 0 ); - class Private { - public: - bool valid; - bool sharing; - bool initDone; - bool crWin; - TQPaintDevice* paintDevice; - TQColor transpColor; -#ifdef TQ_WS_MAC - TQRect oldR; -#endif - }; - Private* d; - - friend class TQGLWidget; -#ifdef TQ_WS_MAC - void fixBufferRect(); -#endif - -private: // Disabled copy constructor and operator= - TQGLContext() {} - TQGLContext( const TQGLContext& ) {} - TQGLContext& operator=( const TQGLContext& ) { return *this; } -}; - - - - -class TQM_EXPORT_OPENGL TQGLWidget : public TQWidget, public TQGL -{ - TQ_OBJECT -public: - TQGLWidget( TQWidget* parent=0, const char* name=0, - const TQGLWidget* shareWidget = 0, WFlags f=0 ); - TQGLWidget( TQGLContext *context, TQWidget* parent, const char* name=0, - const TQGLWidget* shareWidget = 0, WFlags f=0 ); - TQGLWidget( const TQGLFormat& format, TQWidget* parent=0, const char* name=0, - const TQGLWidget* shareWidget = 0, WFlags f=0 ); - ~TQGLWidget(); - - void qglColor( const TQColor& c ) const; - void qglClearColor( const TQColor& c ) const; - - bool isValid() const; - bool isSharing() const; - virtual void makeCurrent(); - void doneCurrent(); - - bool doubleBuffer() const; - virtual void swapBuffers(); - - TQGLFormat format() const; -#ifndef Q_QDOC - virtual void setFormat( const TQGLFormat& format ); -#endif - - const TQGLContext* context() const; -#ifndef Q_QDOC - virtual void setContext( TQGLContext* context, - const TQGLContext* shareContext = 0, - bool deleteOldContext = TRUE ); -#endif - - virtual TQPixmap renderPixmap( int w = 0, int h = 0, - bool useContext = FALSE ); - virtual TQImage grabFrameBuffer( bool withAlpha = FALSE ); - - virtual void makeOverlayCurrent(); - const TQGLContext* overlayContext() const; - - static TQImage convertToGLFormat( const TQImage& img ); - - void setMouseTracking( bool enable ); - virtual void reparent( TQWidget* parent, WFlags f, const TQPoint& p, - bool showIt = FALSE ); - - const TQGLColormap & colormap() const; - void setColormap( const TQGLColormap & map ); - - void renderText( int x, int y, const TQString & str, - const TQFont & fnt = TQFont(), int listBase = 2000 ); - void renderText( double x, double y, double z, const TQString & str, - const TQFont & fnt = TQFont(), int listBase = 2000 ); -public slots: - virtual void updateGL(); - virtual void updateOverlayGL(); - -protected: - virtual void initializeGL(); - virtual void resizeGL( int w, int h ); - virtual void paintGL(); - - virtual void initializeOverlayGL(); - virtual void resizeOverlayGL( int w, int h ); - virtual void paintOverlayGL(); - - void setAutoBufferSwap( bool on ); - bool autoBufferSwap() const; - - void paintEvent( TQPaintEvent* ); - void resizeEvent( TQResizeEvent* ); - - virtual void glInit(); - virtual void glDraw(); - -private: - int displayListBase( const TQFont & fnt, int listBase ); - void cleanupColormaps(); - void init( TQGLContext *context, const TQGLWidget* shareWidget ); - bool renderCxPm( TQPixmap* pm ); - TQGLContext* glcx; - bool autoSwap; - - TQGLColormap cmap; - -#if defined(TQ_WS_WIN) || defined(TQ_WS_MAC) - TQGLContext* olcx; -#elif defined(TQ_WS_X11) - TQGLOverlayWidget* olw; - friend class TQGLOverlayWidget; -#endif - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQGLWidget( const TQGLWidget& ); - TQGLWidget& operator=( const TQGLWidget& ); -#endif - -#if defined(TQ_WS_MAC) -private: - const TQGLContext *slcx; - uint pending_fix : 1, - glcx_dblbuf : 2, - dblbuf : 1, - clp_serial : 15; - TQPixmap *gl_pix; - TQGLFormat req_format; - - void macInternalRecreateContext( TQGLContext *ctx, - const TQGLContext* = NULL, - bool update = TRUE ); - bool macInternalDoubleBuffer( bool fix = TRUE ); - virtual void setRegionDirty( bool ); - virtual void macWidgetChangedWindow(); -#endif -private slots: - void macInternalFixBufferRect(); -}; - - -// -// TQGLFormat inline functions -// - -inline bool TQGLFormat::doubleBuffer() const -{ - return testOption( DoubleBuffer ); -} - -inline bool TQGLFormat::depth() const -{ - return testOption( DepthBuffer ); -} - -inline bool TQGLFormat::rgba() const -{ - return testOption( Rgba ); -} - -inline bool TQGLFormat::alpha() const -{ - return testOption( AlphaChannel ); -} - -inline bool TQGLFormat::accum() const -{ - return testOption( AccumBuffer ); -} - -inline bool TQGLFormat::stencil() const -{ - return testOption( StencilBuffer ); -} - -inline bool TQGLFormat::stereo() const -{ - return testOption( StereoBuffers ); -} - -inline bool TQGLFormat::directRendering() const -{ - return testOption( DirectRendering ); -} - -inline bool TQGLFormat::hasOverlay() const -{ - return testOption( HasOverlay ); -} - -// -// TQGLContext inline functions -// - -inline bool TQGLContext::isValid() const -{ - return d->valid; -} - -inline void TQGLContext::setValid( bool valid ) -{ - d->valid = valid; -} - -inline bool TQGLContext::isSharing() const -{ - return d->sharing; -} - -inline TQGLFormat TQGLContext::format() const -{ - return glFormat; -} - -inline TQGLFormat TQGLContext::requestedFormat() const -{ - return reqFormat; -} - -inline TQPaintDevice* TQGLContext::device() const -{ - return d->paintDevice; -} - -inline bool TQGLContext::deviceIsPixmap() const -{ - return d->paintDevice->devType() == TQInternal::Pixmap; -} - - -inline bool TQGLContext::windowCreated() const -{ - return d->crWin; -} - - -inline void TQGLContext::setWindowCreated( bool on ) -{ - d->crWin = on; -} - -inline bool TQGLContext::initialized() const -{ - return d->initDone; -} - -inline void TQGLContext::setInitialized( bool on ) -{ - d->initDone = on; -} - -inline const TQGLContext* TQGLContext::currentContext() -{ - return currentCtx; -} - -// -// TQGLWidget inline functions -// - -inline TQGLFormat TQGLWidget::format() const -{ - return glcx->format(); -} - -inline const TQGLContext *TQGLWidget::context() const -{ - return glcx; -} - -inline bool TQGLWidget::doubleBuffer() const -{ - return glcx->format().doubleBuffer(); -} - -inline void TQGLWidget::setAutoBufferSwap( bool on ) -{ - autoSwap = on; -} - -inline bool TQGLWidget::autoBufferSwap() const -{ - return autoSwap; -} - -#endif diff --git a/src/opengl/ntqglcolormap.h b/src/opengl/ntqglcolormap.h deleted file mode 100644 index 61fbd7c79..000000000 --- a/src/opengl/ntqglcolormap.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Definition of TQGLColormap class -** -** Created : 20010326 -** -** 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. -** -**********************************************************************/ - -#ifndef TQGLCOLORMAP_H -#define TQGLCOLORMAP_H - -#ifndef QT_H -#include "tqcolor.h" -#include "tqmemarray.h" -#include "ntqshared.h" -#endif // QT_H - -#if !defined( TQT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL ) -#define TQM_EXPORT_OPENGL -#else -#define TQM_EXPORT_OPENGL TQ_EXPORT -#endif - -class TQWidget; -class TQM_EXPORT_OPENGL TQGLColormap -{ -public: - TQGLColormap(); - TQGLColormap( const TQGLColormap & ); - ~TQGLColormap(); - - TQGLColormap &operator=( const TQGLColormap & ); - - bool isEmpty() const; - int size() const; - void detach(); - - void setEntries( int count, const TQRgb * colors, int base = 0 ); - void setEntry( int idx, TQRgb color ); - void setEntry( int idx, const TQColor & color ); - TQRgb entryRgb( int idx ) const; - TQColor entryColor( int idx ) const; - int find( TQRgb color ) const; - int findNearest( TQRgb color ) const; - -private: - class Private : public TQShared - { - public: - Private() { - cells.resize( 256 ); // ### hardcoded to 256 entries for now - cmapHandle = 0; - } - - ~Private() { - } - - TQMemArray cells; - TQt::HANDLE cmapHandle; - }; - - Private * d; - - friend class TQGLWidget; -}; - -#endif diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp deleted file mode 100644 index 8c327941e..000000000 --- a/src/opengl/qgl.cpp +++ /dev/null @@ -1,2367 +0,0 @@ -/**************************************************************************** -** -** 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 "tqpaintdevicemetrics.h" -#include "tqimage.h" -#include "ntqcleanuphandler.h" -#include "tqptrdict.h" - -static TQGLFormat* qgl_default_format = 0; -static TQGLFormat* qgl_default_overlay_format = 0; - -#if defined(TQ_WS_X11) -#include "private/qt_x11_p.h" -#define INT32 dummy_INT32 -#define INT8 dummy_INT8 -#include -#undef INT32 -#undef INT8 -#include "qgl_x11_p.h" -#endif - -static TQCleanupHandler 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 TQt Enterprise Edition. -\endif - - \module OpenGL - \ingroup graphics - \ingroup images - - - Normally you can ignore this class. TQGLWidget and the other - OpenGL* 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. - - * 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 TQt Enterprise Edition. -\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* 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 - - * 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 TQt Enterprise Edition. -\endif - - \ingroup graphics - \ingroup images - \module OpenGL - - An OpenGL* 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. - - * 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(TQ_WS_X11) - qt_resolve_gl_symbols(); - gpm = 0; -#endif - setDevice( dev ); -#if defined(TQ_WS_WIN) - dc = 0; - win = 0; - pixelFormatId = 0; - cmap = 0; -#endif -#if defined(TQ_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 TQt Enterprise Edition. -\endif - - \ingroup graphics - \ingroup images - \mainclass - \module OpenGL - - TQGLWidget provides functionality for displaying OpenGL* - 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. - - * 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 displayListCache; -}; - -static TQPtrDict * qgl_d_ptr = 0; -static TQSingleCleanupHandler< TQPtrDict > qgl_cleanup_d_ptr; - -static TQGLWidgetPrivate * qgl_d( const TQGLWidget * w ) -{ - if ( !qgl_d_ptr ) { - qgl_d_ptr = new TQPtrDict; - 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(TQ_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( TQ_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(TQ_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(TQ_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(TQ_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( TQ_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 (TQ_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( TQ_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 // TQT_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 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* 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/}. - - -* 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 -*/ diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp deleted file mode 100644 index 938228346..000000000 --- a/src/opengl/qgl_x11.cpp +++ /dev/null @@ -1,1406 +0,0 @@ -/**************************************************************************** -** -** 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" - -#if defined(TQ_WS_X11) - -#include "tqmap.h" -#include "ntqpixmap.h" -#include "ntqapplication.h" - -#include "tqintdict.h" -#include "private/tqfontengine_p.h" - -#define INT8 dummy_INT8 -#define INT32 dummy_INT32 -#include -#undef INT8 -#undef INT32 -#include -#include -#include -#include - -// POSIX Large File Support redefines truncate -> truncate64 -#if defined(truncate) -# undef truncate -#endif - -#ifndef QT_DLOPEN_OPENGL -extern "C" { - Status XmuLookupStandardColormap( Display *dpy, int screen, VisualID visualid, - unsigned int depth, Atom property, - Bool replace, Bool retain ); -} -#endif - -#include "qgl_x11_p.h" -#ifdef QT_DLOPEN_OPENGL -#include "ntqlibrary.h" - -extern "C" { -_glCallLists qt_glCallLists; -_glClearColor qt_glClearColor; -_glClearIndex qt_glClearIndex; -_glColor3ub qt_glColor3ub; -_glDeleteLists qt_glDeleteLists; -_glDrawBuffer qt_glDrawBuffer; -_glFlush qt_glFlush; -_glIndexi qt_glIndexi; -_glListBase qt_glListBase; -_glLoadIdentity qt_glLoadIdentity; -_glMatrixMode qt_glMatrixMode; -_glOrtho qt_glOrtho; -_glPopAttrib qt_glPopAttrib; -_glPopMatrix qt_glPopMatrix; -_glPushAttrib qt_glPushAttrib; -_glPushMatrix qt_glPushMatrix; -_glRasterPos2i qt_glRasterPos2i; -_glRasterPos3d qt_glRasterPos3d; -_glReadPixels qt_glReadPixels; -_glViewport qt_glViewport; -_glPixelStorei qt_glPixelStorei; -_glBitmap qt_glBitmap; -_glDrawPixels qt_glDrawPixels; -_glNewList qt_glNewList; -_glGetFloatv qt_glGetFloatv; -_glGetIntegerv qt_glGetIntegerv; -_glEndList qt_glEndList; - -_glXChooseVisual qt_glXChooseVisual; -_glXCreateContext qt_glXCreateContext; -_glXCreateGLXPixmap qt_glXCreateGLXPixmap; -_glXDestroyContext qt_glXDestroyContext; -_glXDestroyGLXPixmap qt_glXDestroyGLXPixmap; -_glXGetClientString qt_glXGetClientString; -_glXGetConfig qt_glXGetConfig; -_glXIsDirect qt_glXIsDirect; -_glXMakeCurrent qt_glXMakeCurrent; -_glXQueryExtension qt_glXQueryExtension; -_glXQueryExtensionsString qt_glXQueryExtensionsString; -_glXQueryServerString qt_glXQueryServerString; -_glXSwapBuffers qt_glXSwapBuffers; -_glXUseXFont qt_glXUseXFont; -_glXWaitX qt_glXWaitX; -}; - -bool qt_resolve_gl_symbols(bool fatal) -{ - static bool gl_syms_resolved = FALSE; - if (gl_syms_resolved) - return TRUE; - - TQLibrary gl("GL.so.1"); - gl.setAutoUnload(FALSE); - - qt_glCallLists = (_glCallLists) gl.resolve("glCallLists"); - - if (!qt_glCallLists) { // if this fails the rest will surely fail - if (fatal) - tqFatal("Unable to resolve GL/GLX symbols - please check your GL library installation."); - return FALSE; - } - - qt_glClearColor = (_glClearColor) gl.resolve("glClearColor"); - qt_glClearIndex = (_glClearIndex) gl.resolve("glClearIndex"); - qt_glColor3ub = (_glColor3ub) gl.resolve("glColor3ub"); - qt_glDeleteLists = (_glDeleteLists) gl.resolve("glDeleteLists"); - qt_glDrawBuffer = (_glDrawBuffer) gl.resolve("glDrawBuffer"); - qt_glFlush = (_glFlush) gl.resolve("glFlush"); - qt_glIndexi = (_glIndexi) gl.resolve("glIndexi"); - qt_glListBase = (_glListBase) gl.resolve("glListBase"); - qt_glLoadIdentity = (_glLoadIdentity) gl.resolve("glLoadIdentity"); - qt_glMatrixMode = (_glMatrixMode) gl.resolve("glMatrixMode"); - qt_glOrtho = (_glOrtho) gl.resolve("glOrtho"); - qt_glPopAttrib = (_glPopAttrib) gl.resolve("glPopAttrib"); - qt_glPopMatrix = (_glPopMatrix) gl.resolve("glPopMatrix"); - qt_glPushAttrib = (_glPushAttrib) gl.resolve("glPushAttrib"); - qt_glPushMatrix = (_glPushMatrix) gl.resolve("glPushMatrix"); - qt_glRasterPos2i = (_glRasterPos2i) gl.resolve("glRasterPos2i"); - qt_glRasterPos3d = (_glRasterPos3d) gl.resolve("glRasterPos3d"); - qt_glReadPixels = (_glReadPixels) gl.resolve("glReadPixels"); - qt_glViewport = (_glViewport) gl.resolve("glViewport"); - qt_glPixelStorei = (_glPixelStorei) gl.resolve("glPixelStorei"); - qt_glBitmap = (_glBitmap) gl.resolve("glBitmap"); - qt_glDrawPixels = (_glDrawPixels) gl.resolve("glDrawPixels"); - qt_glNewList = (_glNewList) gl.resolve("glNewList"); - qt_glGetFloatv = (_glGetFloatv) gl.resolve("glGetFloatv"); - qt_glGetIntegerv = (_glGetIntegerv) gl.resolve("glGetIntegerv"); - qt_glEndList = (_glEndList) gl.resolve("glEndList"); - - qt_glXChooseVisual = (_glXChooseVisual) gl.resolve("glXChooseVisual"); - qt_glXCreateContext = (_glXCreateContext) gl.resolve("glXCreateContext"); - qt_glXCreateGLXPixmap = (_glXCreateGLXPixmap) gl.resolve("glXCreateGLXPixmap"); - qt_glXDestroyContext = (_glXDestroyContext) gl.resolve("glXDestroyContext"); - qt_glXDestroyGLXPixmap = (_glXDestroyGLXPixmap) gl.resolve("glXDestroyGLXPixmap"); - qt_glXGetClientString = (_glXGetClientString) gl.resolve("glXGetClientString"); - qt_glXGetConfig = (_glXGetConfig) gl.resolve("glXGetConfig"); - qt_glXIsDirect = (_glXIsDirect) gl.resolve("glXIsDirect"); - qt_glXMakeCurrent = (_glXMakeCurrent) gl.resolve("glXMakeCurrent"); - qt_glXQueryExtension = (_glXQueryExtension) gl.resolve("glXQueryExtension"); - qt_glXQueryExtensionsString = (_glXQueryExtensionsString) gl.resolve("glXQueryExtensionsString"); - qt_glXQueryServerString = (_glXQueryServerString) gl.resolve("glXQueryServerString"); - qt_glXSwapBuffers = (_glXSwapBuffers) gl.resolve("glXSwapBuffers"); - qt_glXUseXFont = (_glXUseXFont) gl.resolve("glXUseXFont"); - qt_glXWaitX = (_glXWaitX) gl.resolve("glXWaitX"); - gl_syms_resolved = TRUE; - return TRUE; -} -#endif // QT_DLOPEN_OPENGL - - -/* - The choose_cmap function is internal and used by TQGLWidget::setContext() - and GLX (not Windows). If the application can't find any sharable - colormaps, it must at least create as few colormaps as possible. The - dictionary solution below ensures only one colormap is created per visual. - Colormaps are also deleted when the application terminates. -*/ - -struct CMapEntry { - CMapEntry(); - ~CMapEntry(); - Colormap cmap; - bool alloc; - XStandardColormap scmap; -}; - -CMapEntry::CMapEntry() -{ - cmap = 0; - alloc = FALSE; - scmap.colormap = 0; -} - -CMapEntry::~CMapEntry() -{ - if ( alloc ) - XFreeColormap( TQPaintDevice::x11AppDisplay(), cmap ); -} - -static TQIntDict *cmap_dict = 0; -static bool mesa_gl = FALSE; -static TQIntDict< TQMap > *qglcmap_dict = 0; - -static void cleanup_cmaps() -{ - if (cmap_dict) { - cmap_dict->setAutoDelete(TRUE); - delete cmap_dict; - cmap_dict = 0; - } - if (qglcmap_dict) { - qglcmap_dict->setAutoDelete(TRUE); - delete qglcmap_dict; - qglcmap_dict = 0; - } -} - -static Colormap choose_cmap( Display *dpy, XVisualInfo *vi ) -{ - if ( !cmap_dict ) { - cmap_dict = new TQIntDict; - const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION ); - if ( v ) - mesa_gl = strstr(v,"Mesa") != 0; - tqAddPostRoutine( cleanup_cmaps ); - } - - CMapEntry *x = cmap_dict->find( (long) vi->visualid + ( vi->screen * 256 ) ); - if ( x ) // found colormap for visual - return x->cmap; - - x = new CMapEntry(); - - XStandardColormap *c; - int n, i; - - // tqDebug( "Choosing cmap for vID %0x", vi->visualid ); - - if ( vi->visualid == - XVisualIDFromVisual( (Visual*)TQPaintDevice::x11AppVisual( vi->screen ) ) ) { - // tqDebug( "Using x11AppColormap" ); - return TQPaintDevice::x11AppColormap( vi->screen ); - } - - if ( mesa_gl ) { // we're using MesaGL - Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", TRUE ); - if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 ) { - if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - hp_cmaps) ) { - i = 0; - while ( i < n && x->cmap == 0 ) { - if ( c[i].visualid == vi->visual->visualid ) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //tqDebug( "Using HP_RGB scmap" ); - - } - i++; - } - XFree( (char *)c ); - } - } - } -#if !defined(Q_OS_SOLARIS) - if ( !x->cmap ) { -#ifdef QT_DLOPEN_OPENGL - typedef Status (*_XmuLookupStandardColormap)( Display *dpy, int screen, VisualID visualid, unsigned int depth, - Atom property, Bool replace, Bool retain ); - _XmuLookupStandardColormap qt_XmuLookupStandardColormap; - qt_XmuLookupStandardColormap = (_XmuLookupStandardColormap) TQLibrary::resolve("Xmu.so.6", "XmuLookupStandardColormap"); - if (!qt_XmuLookupStandardColormap) - tqFatal("Unable to resolve Xmu symbols - please check your Xmu library installation."); -#define XmuLookupStandardColormap qt_XmuLookupStandardColormap - -#endif - - if ( XmuLookupStandardColormap(dpy,vi->screen,vi->visualid,vi->depth, - XA_RGB_DEFAULT_MAP,FALSE,TRUE) ) { - if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, - XA_RGB_DEFAULT_MAP) ) { - i = 0; - while ( i < n && x->cmap == 0 ) { - if ( c[i].visualid == vi->visualid ) { - x->cmap = c[i].colormap; - x->scmap = c[i]; - //tqDebug( "Using RGB_DEFAULT scmap" ); - } - i++; - } - XFree( (char *)c ); - } - } - } -#endif - if ( !x->cmap ) { // no shared cmap found - x->cmap = XCreateColormap( dpy, RootWindow(dpy,vi->screen), vi->visual, - AllocNone ); - x->alloc = TRUE; - // tqDebug( "Allocating cmap" ); - } - - // associate cmap with visualid - cmap_dict->insert( (long) vi->visualid + ( vi->screen * 256 ), x ); - return x->cmap; -} - -struct TransColor -{ - VisualID vis; - int screen; - long color; -}; - -static TQMemArray trans_colors; -static int trans_colors_init = FALSE; - - -static void find_trans_colors() -{ - struct OverlayProp { - long visual; - long type; - long value; - long layer; - }; - - trans_colors_init = TRUE; - - Display* appDisplay = TQPaintDevice::x11AppDisplay(); - - int scr; - int lastsize = 0; - for ( scr = 0; scr < ScreenCount( appDisplay ); scr++ ) { - TQWidget* rootWin = TQApplication::desktop()->screen( scr ); - if ( !rootWin ) - return; // Should not happen - Atom overlayVisualsAtom = XInternAtom( appDisplay, - "SERVER_OVERLAY_VISUALS", True ); - if ( overlayVisualsAtom == None ) - return; // Server has no overlays - - Atom actualType; - int actualFormat; - ulong nItems; - ulong bytesAfter; - OverlayProp* overlayProps = 0; - int res = XGetWindowProperty( appDisplay, rootWin->winId(), - overlayVisualsAtom, 0, 10000, False, - overlayVisualsAtom, &actualType, - &actualFormat, &nItems, &bytesAfter, - (uchar**)&overlayProps ); - - if ( res != Success || actualType != overlayVisualsAtom - || actualFormat != 32 || nItems < 4 || !overlayProps ) - return; // Error reading property - - int numProps = nItems / 4; - trans_colors.resize( lastsize + numProps ); - int j = lastsize; - for ( int i = 0; i < numProps; i++ ) { - if ( overlayProps[i].type == 1 ) { - trans_colors[j].vis = (VisualID)overlayProps[i].visual; - trans_colors[j].screen = scr; - trans_colors[j].color = (int)overlayProps[i].value; - j++; - } - } - XFree( overlayProps ); - lastsize = j; - trans_colors.truncate( lastsize ); - } -} - - -/***************************************************************************** - TQGLFormat UNIX/GLX-specific code - *****************************************************************************/ - -bool TQGLFormat::hasOpenGL() -{ - if (!qt_resolve_gl_symbols(FALSE)) - return FALSE; - return glXQueryExtension(tqt_xdisplay(),0,0) != 0; -} - - -bool TQGLFormat::hasOpenGLOverlays() -{ - qt_resolve_gl_symbols(); - if ( !trans_colors_init ) - find_trans_colors(); - return trans_colors.size() > 0; -} - - - -/***************************************************************************** - TQGLContext UNIX/GLX-specific code - *****************************************************************************/ - -bool TQGLContext::chooseContext( const TQGLContext* shareContext ) -{ - Display* disp = d->paintDevice->x11Display(); - vi = chooseVisual(); - if ( !vi ) - return FALSE; - - if ( deviceIsPixmap() && - (((XVisualInfo*)vi)->depth != d->paintDevice->x11Depth() || - ((XVisualInfo*)vi)->screen != d->paintDevice->x11Screen()) ) - { - XFree( vi ); - XVisualInfo appVisInfo; - memset( &appVisInfo, 0, sizeof(XVisualInfo) ); - appVisInfo.visualid = XVisualIDFromVisual( (Visual*)d->paintDevice->x11Visual() ); - appVisInfo.screen = d->paintDevice->x11Screen(); - int nvis; - vi = XGetVisualInfo( disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis ); - if ( !vi ) - return FALSE; - - int useGL; - glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL ); - if ( !useGL ) - return FALSE; //# Chickening out already... - } - int res; - glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res ); - glFormat.setPlane( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res ); - glFormat.setDoubleBuffer( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res ); - glFormat.setDepth( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res ); - glFormat.setRgba( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res ); - glFormat.setAlpha( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res ); - glFormat.setAccum( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res ); - glFormat.setStencil( res ); - glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res ); - glFormat.setStereo( res ); - - Bool direct = format().directRendering() ? True : False; - - if ( shareContext && - ( !shareContext->isValid() || !shareContext->cx ) ) { -#if defined(QT_CHECK_NULL) - tqWarning("TQGLContext::chooseContext(): Cannot share with invalid context"); -#endif - shareContext = 0; - } - - // 1. Sharing between rgba and color-index will give wrong colors. - // 2. Contexts cannot be shared btw. direct/non-direct renderers. - // 3. Pixmaps cannot share contexts that are set up for direct rendering. - if ( shareContext && (format().rgba() != shareContext->format().rgba() || - (deviceIsPixmap() && - glXIsDirect( disp, (GLXContext)shareContext->cx )))) - shareContext = 0; - - cx = 0; - if ( shareContext ) { - cx = glXCreateContext( disp, (XVisualInfo *)vi, - (GLXContext)shareContext->cx, direct ); - if ( cx ) - d->sharing = TRUE; - } - if ( !cx ) - cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct ); - if ( !cx ) - return FALSE; - glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) ); - if ( deviceIsPixmap() ) { -#if defined(GLX_MESA_pixmap_colormap) && defined(TQGL_USE_MESA_EXT) - gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi, - d->paintDevice->handle(), - choose_cmap( disp, (XVisualInfo *)vi ) ); -#else - gpm = (TQ_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi, - d->paintDevice->handle() ); -#endif - if ( !gpm ) - return FALSE; - } - return TRUE; -} - - -/*! - X11 only: This virtual function tries to find a - visual that matches the format, reducing the demands if the original - request cannot be met. - - The algorithm for reducing the demands of the format is quite - simple-minded, so override this method in your subclass if your - application has spcific requirements on visual selection. - - \sa chooseContext() -*/ - -void *TQGLContext::chooseVisual() -{ - static int bufDepths[] = { 8, 4, 2, 1 }; // Try 16, 12 also? - //todo: if pixmap, also make sure that vi->depth == pixmap->depth - void* vis = 0; - int i = 0; - bool fail = FALSE; - TQGLFormat fmt = format(); - bool tryDouble = !fmt.doubleBuffer(); // Some GL impl's only have double - bool triedDouble = FALSE; - while( !fail && !( vis = tryVisual( fmt, bufDepths[i] ) ) ) { - if ( !fmt.rgba() && bufDepths[i] > 1 ) { - i++; - continue; - } - if ( tryDouble ) { - fmt.setDoubleBuffer( TRUE ); - tryDouble = FALSE; - triedDouble = TRUE; - continue; - } - else if ( triedDouble ) { - fmt.setDoubleBuffer( FALSE ); - triedDouble = FALSE; - } - if ( fmt.stereo() ) { - fmt.setStereo( FALSE ); - continue; - } - if ( fmt.accum() ) { - fmt.setAccum( FALSE ); - continue; - } - if ( fmt.stencil() ) { - fmt.setStencil( FALSE ); - continue; - } - if ( fmt.alpha() ) { - fmt.setAlpha( FALSE ); - continue; - } - if ( fmt.depth() ) { - fmt.setDepth( FALSE ); - continue; - } - if ( fmt.doubleBuffer() ) { - fmt.setDoubleBuffer( FALSE ); - continue; - } - fail = TRUE; - } - glFormat = fmt; - return vis; -} - - -/*! - - \internal - - X11 only: This virtual function chooses a visual - that matches the OpenGL \link format() format\endlink. Reimplement this - function in a subclass if you need a custom visual. - - \sa chooseContext() -*/ - -void *TQGLContext::tryVisual( const TQGLFormat& f, int bufDepth ) -{ - int spec[40]; - int i = 0; - spec[i++] = GLX_LEVEL; - spec[i++] = f.plane(); - -#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) - static bool useTranspExt = FALSE; - static bool useTranspExtChecked = FALSE; - if ( f.plane() && !useTranspExtChecked && d->paintDevice ) { - TQCString estr( glXQueryExtensionsString( d->paintDevice->x11Display(), - d->paintDevice->x11Screen() ) ); - useTranspExt = estr.contains( "GLX_EXT_visual_info" ); - //# (A bit simplistic; that could theoretically be a substring) - if ( useTranspExt ) { - TQCString cstr( glXGetClientString( d->paintDevice->x11Display(), - GLX_VENDOR ) ); - useTranspExt = !cstr.contains( "Xi Graphics" ); // bug workaround - if ( useTranspExt ) { - // bug workaround - some systems (eg. FireGL) refuses to return an overlay - // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specfied, even if - // the implementation supports transparent overlays - int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, - f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, - None }; - XVisualInfo * vinf = glXChooseVisual( d->paintDevice->x11Display(), - d->paintDevice->x11Screen(), tmpSpec ); - if ( !vinf ) { - useTranspExt = FALSE; - } - } - } - - useTranspExtChecked = TRUE; - } - if ( f.plane() && useTranspExt ) { - // Required to avoid non-transparent overlay visual(!) on some systems - spec[i++] = GLX_TRANSPARENT_TYPE_EXT; - spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; - } -#endif - - if ( f.doubleBuffer() ) - spec[i++] = GLX_DOUBLEBUFFER; - if ( f.depth() ) { - spec[i++] = GLX_DEPTH_SIZE; - spec[i++] = 1; - } - if ( f.stereo() ) { - spec[i++] = GLX_STEREO; - } - if ( f.stencil() ) { - spec[i++] = GLX_STENCIL_SIZE; - spec[i++] = 1; - } - if ( f.rgba() ) { - spec[i++] = GLX_RGBA; - spec[i++] = GLX_RED_SIZE; - spec[i++] = 1; - spec[i++] = GLX_GREEN_SIZE; - spec[i++] = 1; - spec[i++] = GLX_BLUE_SIZE; - spec[i++] = 1; - if ( f.alpha() ) { - spec[i++] = GLX_ALPHA_SIZE; - spec[i++] = 1; - } - if ( f.accum() ) { - spec[i++] = GLX_ACCUM_RED_SIZE; - spec[i++] = 1; - spec[i++] = GLX_ACCUM_GREEN_SIZE; - spec[i++] = 1; - spec[i++] = GLX_ACCUM_BLUE_SIZE; - spec[i++] = 1; - if ( f.alpha() ) { - spec[i++] = GLX_ACCUM_ALPHA_SIZE; - spec[i++] = 1; - } - } - } - else { - spec[i++] = GLX_BUFFER_SIZE; - spec[i++] = bufDepth; - } - - spec[i] = None; - return glXChooseVisual( d->paintDevice->x11Display(), - d->paintDevice->x11Screen(), spec ); -} - - -void TQGLContext::reset() -{ - if ( !d->valid ) - return; - doneCurrent(); - if ( gpm ) - glXDestroyGLXPixmap( d->paintDevice->x11Display(), (GLXPixmap)gpm ); - gpm = 0; - glXDestroyContext( d->paintDevice->x11Display(), (GLXContext)cx ); - if ( vi ) - XFree( vi ); - vi = 0; - cx = 0; - d->crWin = FALSE; - d->sharing = FALSE; - d->valid = FALSE; - d->transpColor = TQColor(); - d->initDone = FALSE; -} - - -void TQGLContext::makeCurrent() -{ - if ( !d->valid ) { -#if defined(QT_CHECK_STATE) - tqWarning("TQGLContext::makeCurrent(): Cannot make invalid context current."); -#endif - return; - } - bool ok = TRUE; - if ( deviceIsPixmap() ) - ok = glXMakeCurrent( d->paintDevice->x11Display(), - (GLXPixmap)gpm, - (GLXContext)cx ); - - else - ok = glXMakeCurrent( d->paintDevice->x11Display(), - ((TQWidget *)d->paintDevice)->winId(), - (GLXContext)cx ); -#if defined(QT_CHECK_NULL) - // tqDebug("makeCurrent: %i, vi=%i, vi->vi=%i, vi->id=%i", (int)this, (int)vi, (int)((XVisualInfo*)vi)->visual, (int)((XVisualInfo*)vi)->visualid ); - if ( !ok ) - tqWarning("TQGLContext::makeCurrent(): Failed."); -#endif - if ( ok ) - currentCtx = this; -} - -void TQGLContext::doneCurrent() -{ - glXMakeCurrent( d->paintDevice->x11Display(), 0, 0 ); - currentCtx = 0; -} - - -void TQGLContext::swapBuffers() const -{ - if ( !d->valid ) - return; - if ( !deviceIsPixmap() ) - glXSwapBuffers( d->paintDevice->x11Display(), - ((TQWidget *)d->paintDevice)->winId() ); -} - -TQColor TQGLContext::overlayTransparentColor() const -{ - //### make more efficient using the transpColor member - if ( isValid() ) { - if ( !trans_colors_init ) - find_trans_colors(); - - VisualID myVisualId = ((XVisualInfo*)vi)->visualid; - int myScreen = ((XVisualInfo*)vi)->screen; - for ( int i = 0; i < (int)trans_colors.size(); i++ ) { - if ( trans_colors[i].vis == myVisualId && - trans_colors[i].screen == myScreen ) { - XColor col; - col.pixel = trans_colors[i].color; - col.red = col.green = col.blue = 0; - col.flags = 0; - Display *dpy = d->paintDevice->x11Display(); - if (col.pixel > (uint) ((XVisualInfo *)vi)->colormap_size - 1) - col.pixel = ((XVisualInfo *)vi)->colormap_size - 1; - XQueryColor(dpy, choose_cmap(dpy, (XVisualInfo *) vi), &col); - uchar r = (uchar)((col.red / 65535.0) * 255.0 + 0.5); - uchar g = (uchar)((col.green / 65535.0) * 255.0 + 0.5); - uchar b = (uchar)((col.blue / 65535.0) * 255.0 + 0.5); - return TQColor(tqRgb(r,g,b), trans_colors[i].color); - } - } - } - return TQColor(); // Invalid color -} - - -uint TQGLContext::colorIndex( const TQColor& c ) const -{ - int screen = ((XVisualInfo *)vi)->screen; - if ( isValid() ) { - if ( format().plane() - && c.pixel( screen ) == overlayTransparentColor().pixel( screen ) ) - return c.pixel( screen ); // Special; don't look-up - if ( ((XVisualInfo*)vi)->visualid == - XVisualIDFromVisual( (Visual*)TQPaintDevice::x11AppVisual( screen ) ) ) - return c.pixel( screen ); // We're using TQColor's cmap - - XVisualInfo *info = (XVisualInfo *) vi; - CMapEntry *x = cmap_dict->find( (long) info->visualid + ( info->screen * 256 ) ); - if ( x && !x->alloc) { // It's a standard colormap - int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0); - int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0); - int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0); - uint p = x->scmap.base_pixel - + ( rf * x->scmap.red_mult ) - + ( gf * x->scmap.green_mult ) - + ( bf * x->scmap.blue_mult ); - return p; - } else { - if (!qglcmap_dict) { - qglcmap_dict = new TQIntDict< TQMap >; - } - TQMap *cmap; - if ((cmap = qglcmap_dict->find((long) info->visualid)) == 0) { - cmap = new TQMap; - qglcmap_dict->insert((long) info->visualid, cmap); - } - - // already in the map? - TQRgb target = c.rgb(); - TQMap::Iterator it = cmap->begin(); - for (; it != cmap->end(); ++it) { - if ((*it) == target) - return it.key(); - } - - // need to alloc color - unsigned long plane_mask[2]; - unsigned long color_map_entry; - if (!XAllocColorCells (TQPaintDevice::x11AppDisplay(), x->cmap, TRUE, plane_mask, 0, - &color_map_entry, 1)) - return c.pixel(screen); - - XColor col; - col.flags = DoRed | DoGreen | DoBlue; - col.pixel = color_map_entry; - col.red = (ushort)((tqRed(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.green = (ushort)((tqGreen(c.rgb()) / 255.0) * 65535.0 + 0.5); - col.blue = (ushort)((tqBlue(c.rgb()) / 255.0) * 65535.0 + 0.5); - XStoreColor(TQPaintDevice::x11AppDisplay(), x->cmap, &col); - - cmap->insert(color_map_entry, target); - return color_map_entry; - } - } - return 0; -} - -#ifndef TQT_NO_XFTFREETYPE -/*! \internal - This is basically a substitute for glxUseXFont() which can only - handle XLFD fonts. This version relies on XFT v2 to render the - glyphs, but it works with all fonts that XFT2 provides - both - antialiased and aliased bitmap and outline fonts. -*/ -void qgl_use_font(TQFontEngineXft *engine, int first, int count, int listBase) -{ - GLfloat color[4]; - glGetFloatv(GL_CURRENT_COLOR, color); - - // save the pixel unpack state - GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; - glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); - glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); - glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); - glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); - glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); - glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); - - glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - Bool antialiased = False; -#if 0 // disable antialias support for now - XftPatternGetBool(engine->pattern(), XFT_ANTIALIAS, 0, &antialiased); -#endif -#ifdef QT_XFT2 - FT_Face face = XftLockFace(engine->font()); -#else - FT_Face face = engine->face(); -#endif - // start generating font glyphs - for (int i = first; i < count; ++i) { - int list = listBase + i; - GLfloat x0, y0, dx, dy; - - FT_Error err; - - err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); - if (err) { - tqDebug("failed loading glyph %d from font", i); - Q_ASSERT(!err); - } - err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal - : ft_render_mode_mono)); - if (err) { - tqDebug("failed rendering glyph %d from font", i); - Q_ASSERT(!err); - } - - FT_Bitmap bm = face->glyph->bitmap; - x0 = face->glyph->metrics.horiBearingX >> 6; - y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; - dx = face->glyph->metrics.horiAdvance >> 6; - dy = 0; - int sz = bm.pitch * bm.rows; - uint *aa_glyph = 0; - uchar *ua_glyph = 0; - - if (antialiased) - aa_glyph = new uint[sz]; - else - ua_glyph = new uchar[sz]; - - // convert to GL format - for (int y = 0; y < bm.rows; ++y) { - for (int x = 0; x < bm.pitch; ++x) { - int c1 = y*bm.pitch + x; - int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; - if (antialiased) { - aa_glyph[c1] = (int(color[0]*255) << 24) - | (int(color[1]*255) << 16) - | (int(color[2]*255) << 8) | bm.buffer[c2]; - } else { - ua_glyph[c1] = bm.buffer[c2]; - } - } - } - - glNewList(list, GL_COMPILE); - if (antialiased) { - // calling glBitmap() is just a trick to move the current - // raster pos, since glGet*() won't work in display lists - glBitmap(0, 0, 0, 0, x0, -y0, 0); - glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); - glBitmap(0, 0, 0, 0, dx-x0, y0, 0); - } else { - glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); - } - glEndList(); - antialiased ? delete[] aa_glyph : delete[] ua_glyph; - } - -#ifdef QT_XFT2 - XftUnlockFace(engine->font()); -#endif - - // restore pixel unpack settings - glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); - glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); - glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); - glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); -} -#endif - -void TQGLContext::generateFontDisplayLists( const TQFont & fnt, int listBase ) -{ - TQFont f(fnt); - TQFontEngine *engine = f.d->engineForScript(TQFont::Latin); - -#ifndef TQT_NO_XFTFREETYPE - if(engine->type() == TQFontEngine::Xft) { - qgl_use_font((TQFontEngineXft *) engine, 0, 256, listBase); - return; - } -#endif - // glXUseXFont() only works with XLFD font structures and a few GL - // drivers crash if 0 is passed as the font handle - f.setStyleStrategy(TQFont::OpenGLCompatible); - if (f.handle() && (engine->type() == TQFontEngine::XLFD - || engine->type() == TQFontEngine::LatinXLFD)) { - glXUseXFont((Font) f.handle(), 0, 256, listBase); - } -} - -/***************************************************************************** - TQGLOverlayWidget (Internal overlay class for X11) - *****************************************************************************/ - -class TQGLOverlayWidget : public TQGLWidget -{ - TQ_OBJECT -public: - TQGLOverlayWidget( const TQGLFormat& format, TQGLWidget* parent, - const char* name=0, const TQGLWidget* shareWidget=0 ); - -protected: - void initializeGL(); - void paintGL(); - void resizeGL( int w, int h ); - -private: - TQGLWidget* realWidget; - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQGLOverlayWidget( const TQGLOverlayWidget& ); - TQGLOverlayWidget& operator=( const TQGLOverlayWidget& ); -#endif -}; - - -TQGLOverlayWidget::TQGLOverlayWidget( const TQGLFormat& format, TQGLWidget* parent, - const char* name, - const TQGLWidget* shareWidget ) - : TQGLWidget( format, parent, name, shareWidget ? shareWidget->olw : 0 ) -{ - realWidget = parent; -} - - - -void TQGLOverlayWidget::initializeGL() -{ - TQColor transparentColor = context()->overlayTransparentColor(); - if ( transparentColor.isValid() ) - qglClearColor( transparentColor ); - else - tqWarning( "TQGLOverlayWidget::initializeGL(): Could not get transparent color" ); - realWidget->initializeOverlayGL(); -} - - -void TQGLOverlayWidget::resizeGL( int w, int h ) -{ - glViewport( 0, 0, w, h ); - realWidget->resizeOverlayGL( w, h ); -} - - -void TQGLOverlayWidget::paintGL() -{ - realWidget->paintOverlayGL(); -} - -#undef Bool -#include "qgl_x11.moc" - -/***************************************************************************** - TQGLWidget UNIX/GLX-specific code - *****************************************************************************/ -void TQGLWidget::init( TQGLContext *context, const TQGLWidget *shareWidget ) -{ - qt_resolve_gl_symbols(); - - glcx = 0; - olw = 0; - autoSwap = TRUE; - if ( !context->device() ) - context->setDevice( this ); - - if ( shareWidget ) - setContext( context, shareWidget->context() ); - else - setContext( context ); - setBackgroundMode( NoBackground ); - - if ( isValid() && context->format().hasOverlay() ) { - TQCString olwName( name() ); - olwName += "-TQGL_internal_overlay_widget"; - olw = new TQGLOverlayWidget( TQGLFormat::defaultOverlayFormat(), - this, olwName, shareWidget ); - if ( olw->isValid() ) { - olw->setAutoBufferSwap( FALSE ); - olw->setFocusProxy( this ); - } - else { - delete olw; - olw = 0; - glcx->glFormat.setOverlay( FALSE ); - } - } -} - -/*! \reimp */ -void TQGLWidget::reparent( TQWidget* parent, WFlags f, const TQPoint& p, - bool showIt ) -{ - if (glcx) - glcx->doneCurrent(); - TQWidget::reparent( parent, f, p, FALSE ); - if ( showIt ) - show(); -} - - -void TQGLWidget::setMouseTracking( bool enable ) -{ - if ( olw ) - olw->setMouseTracking( enable ); - TQWidget::setMouseTracking( enable ); -} - - -void TQGLWidget::resizeEvent( TQResizeEvent * ) -{ - if ( !isValid() ) - return; - makeCurrent(); - if ( !glcx->initialized() ) - glInit(); - glXWaitX(); - resizeGL( width(), height() ); - if ( olw ) - olw->setGeometry( rect() ); -} - -const TQGLContext* TQGLWidget::overlayContext() const -{ - if ( olw ) - return olw->context(); - else - return 0; -} - - -void TQGLWidget::makeOverlayCurrent() -{ - if ( olw ) - olw->makeCurrent(); -} - - -void TQGLWidget::updateOverlayGL() -{ - if ( olw ) - olw->updateGL(); -} - -void TQGLWidget::setContext( TQGLContext *context, - const TQGLContext* shareContext, - bool deleteOldContext ) -{ - if ( context == 0 ) { -#if defined(QT_CHECK_NULL) - tqWarning( "TQGLWidget::setContext: Cannot set null context" ); -#endif - return; - } - if ( !context->deviceIsPixmap() && context->device() != this ) { -#if defined(QT_CHECK_STATE) - tqWarning( "TQGLWidget::setContext: Context must refer to this widget" ); -#endif - return; - } - - if ( glcx ) - glcx->doneCurrent(); - TQGLContext* oldcx = glcx; - glcx = context; - - bool createFailed = FALSE; - if ( !glcx->isValid() ) { - if ( !glcx->create( shareContext ? shareContext : oldcx ) ) - createFailed = TRUE; - } - if ( createFailed ) { - if ( deleteOldContext ) - delete oldcx; - return; - } - - if ( glcx->windowCreated() || glcx->deviceIsPixmap() ) { - if ( deleteOldContext ) - delete oldcx; - return; - } - - bool visible = isVisible(); - if ( visible ) - hide(); - - XVisualInfo *vi = (XVisualInfo*)glcx->vi; - XSetWindowAttributes a; - - a.colormap = choose_cmap( x11Display(), vi ); // find best colormap - a.background_pixel = backgroundColor().pixel( vi->screen ); - a.border_pixel = black.pixel( vi->screen ); - Window p = RootWindow( x11Display(), vi->screen ); - if ( parentWidget() ) - p = parentWidget()->winId(); - - Window w = XCreateWindow( x11Display(), p, x(), y(), width(), height(), - 0, vi->depth, InputOutput, vi->visual, - CWBackPixel|CWBorderPixel|CWColormap, &a ); - - Window *cmw; - Window *cmwret; - int count; - if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(), - &cmwret, &count ) ) { - cmw = new Window[count+1]; - memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count ); - XFree( (char *)cmwret ); - int i; - for ( i=0; i= count ) // append new window - cmw[count++] = w; - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = w; - } - -#if defined(GLX_MESA_release_buffers) && defined(TQGL_USE_MESA_EXT) - if ( oldcx && oldcx->windowCreated() ) - glXReleaseBuffersMESA( x11Display(), winId() ); -#endif - if ( deleteOldContext ) - delete oldcx; - oldcx = 0; - - create( w ); - - XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw, - count ); - delete [] cmw; - - if ( visible ) - show(); - XFlush( x11Display() ); - glcx->setWindowCreated( TRUE ); -} - - -bool TQGLWidget::renderCxPm( TQPixmap* pm ) -{ - if ( ((XVisualInfo*)glcx->vi)->depth != pm->depth() ) - return FALSE; - - GLXPixmap glPm; -#if defined(GLX_MESA_pixmap_colormap) && defined(TQGL_USE_MESA_EXT) - glPm = glXCreateGLXPixmapMESA( x11Display(), - (XVisualInfo*)glcx->vi, - (Pixmap)pm->handle(), - choose_cmap( pm->x11Display(), - (XVisualInfo*)glcx->vi ) ); -#else - glPm = (TQ_UINT32)glXCreateGLXPixmap( x11Display(), - (XVisualInfo*)glcx->vi, - (Pixmap)pm->handle() ); -#endif - - if ( !glXMakeCurrent( x11Display(), glPm, (GLXContext)glcx->cx ) ) { - glXDestroyGLXPixmap( x11Display(), glPm ); - return FALSE; - } - - glDrawBuffer( GL_FRONT ); - if ( !glcx->initialized() ) - glInit(); - resizeGL( pm->width(), pm->height() ); - paintGL(); - glFlush(); - makeCurrent(); - glXDestroyGLXPixmap( x11Display(), glPm ); - resizeGL( width(), height() ); - return TRUE; -} - -const TQGLColormap & TQGLWidget::colormap() const -{ - return cmap; -} - -/*\internal - Store color values in the given colormap. -*/ -static void qStoreColors( TQWidget * tlw, Colormap cmap, - const TQGLColormap & cols ) -{ - XColor c; - TQRgb color; - - for ( int i = 0; i < cols.size(); i++ ) { - color = cols.entryRgb( i ); - c.pixel = i; - c.red = (ushort)( (tqRed( color ) / 255.0) * 65535.0 + 0.5 ); - c.green = (ushort)( (tqGreen( color ) / 255.0) * 65535.0 + 0.5 ); - c.blue = (ushort)( (tqBlue( color ) / 255.0) * 65535.0 + 0.5 ); - c.flags = DoRed | DoGreen | DoBlue; - XStoreColor( tlw->x11Display(), cmap, &c ); - } -} - -/*\internal - Check whether the given visual supports dynamic colormaps or not. -*/ -static bool qCanAllocColors( TQWidget * w ) -{ - bool validVisual = FALSE; - int numVisuals; - long mask; - XVisualInfo templ; - XVisualInfo * visuals; - VisualID id = XVisualIDFromVisual( (Visual *) - w->topLevelWidget()->x11Visual() ); - - mask = VisualScreenMask; - templ.screen = w->x11Screen(); - visuals = XGetVisualInfo( w->x11Display(), mask, &templ, &numVisuals ); - - for ( int i = 0; i < numVisuals; i++ ) { - if ( visuals[i].visualid == id ) { - switch ( visuals[i].c_class ) { - case TrueColor: - case StaticColor: - case StaticGray: - case GrayScale: - validVisual = FALSE; - break; - case DirectColor: - case PseudoColor: - validVisual = TRUE; - break; - } - break; - } - } - XFree( visuals ); - - if ( !validVisual ) - return FALSE; - return TRUE; -} - -void TQGLWidget::setColormap( const TQGLColormap & c ) -{ - TQWidget * tlw = topLevelWidget(); // must return a valid widget - - cmap = c; - if ( !cmap.d ) - return; - - if ( !cmap.d->cmapHandle && !qCanAllocColors( this ) ) { - tqWarning( "TQGLWidget::setColormap: Cannot create a read/write " - "colormap for this visual" ); - return; - } - - // If the child GL widget is not of the same visual class as the - // toplevel widget we will get in trouble.. - Window wid = tlw->winId(); - Visual * vis = (Visual *) tlw->x11Visual();; - VisualID cvId = XVisualIDFromVisual( (Visual *) x11Visual() ); - VisualID tvId = XVisualIDFromVisual( (Visual *) tlw->x11Visual() ); - if ( cvId != tvId ) { - wid = winId(); - vis = (Visual *) x11Visual(); - } - - if ( !cmap.d->cmapHandle ) // allocate a cmap if necessary - cmap.d->cmapHandle = XCreateColormap( x11Display(), wid, vis, - AllocAll ); - - qStoreColors( this, (Colormap) cmap.d->cmapHandle, c ); - XSetWindowColormap( x11Display(), wid, (Colormap) cmap.d->cmapHandle ); - - // tell the wm that this window has a special colormap - Window * cmw; - Window * cmwret; - int count; - if ( XGetWMColormapWindows( x11Display(), tlw->winId(), &cmwret, - &count ) ) - { - cmw = new Window[count+1]; - memcpy( (char *) cmw, (char *) cmwret, sizeof(Window) * count ); - XFree( (char *) cmwret ); - int i; - for ( i = 0; i < count; i++ ) { - if ( cmw[i] == winId() ) { - break; - } - } - if ( i >= count ) // append new window only if not in the list - cmw[count++] = winId(); - } else { - count = 1; - cmw = new Window[count]; - cmw[0] = winId(); - } - XSetWMColormapWindows( x11Display(), tlw->winId(), cmw, count ); - delete [] cmw; -} - -/*! \internal - Free up any allocated colormaps. This fn is only called for - top-level widgets. -*/ -void TQGLWidget::cleanupColormaps() -{ - if ( !cmap.d ) - return; - - if ( cmap.d->cmapHandle ) { - XFreeColormap( topLevelWidget()->x11Display(), - (Colormap) cmap.d->cmapHandle ); - cmap.d->cmapHandle = 0; - } -} - -void TQGLWidget::macInternalFixBufferRect() -{ -} - -#endif diff --git a/src/opengl/qgl_x11_p.h b/src/opengl/qgl_x11_p.h deleted file mode 100644 index cbcd741b9..000000000 --- a/src/opengl/qgl_x11_p.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** Definitions needed for resolving GL/GLX symbols using dlopen() -** under X11. -** -** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the OpenGL module of the 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. -** -** 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. -** -**********************************************************************/ - -#ifndef TQGL_P_H -#define TQGL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the TQt API. This header file may -// change from version to version without notice, or even be -// removed. -// -// We mean it. -// -// - -#ifdef QT_DLOPEN_OPENGL -// resolve the GL symbols we use ourselves -bool qt_resolve_gl_symbols(bool = TRUE); -extern "C" { -// GL symbols -typedef void (*_glCallLists)( GLsizei n, GLenum type, const GLvoid *lists ); -typedef void (*_glClearColor)( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); -typedef void (*_glClearIndex)( GLfloat c ); -typedef void (*_glColor3ub)( GLubyte red, GLubyte green, GLubyte blue ); -typedef void (*_glDeleteLists)( GLuint list, GLsizei range ); -typedef void (*_glDrawBuffer)( GLenum mode ); -typedef void (*_glFlush)( void ); -typedef void (*_glIndexi)( GLint c ); -typedef void (*_glListBase)( GLuint base ); -typedef void (*_glLoadIdentity)( void ); -typedef void (*_glMatrixMode)( GLenum mode ); -typedef void (*_glOrtho)( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val ); -typedef void (*_glPopAttrib)( void ); -typedef void (*_glPopMatrix)( void ); -typedef void (*_glPushAttrib)( GLbitfield mask ); -typedef void (*_glPushMatrix)( void ); -typedef void (*_glRasterPos2i)( GLint x, GLint y ); -typedef void (*_glRasterPos3d)( GLdouble x, GLdouble y, GLdouble z ); -typedef void (*_glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); -typedef void (*_glViewport)( GLint x, GLint y, GLsizei width, GLsizei height ); -typedef void (*_glPixelStorei)( GLenum pname, GLint param ); -typedef void (*_glBitmap)( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, - const GLubyte *bitmap ); -typedef void (*_glDrawPixels)( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ); -typedef void (*_glNewList)( GLuint list, GLenum mode ); -typedef void (*_glGetFloatv)( GLenum pname, GLfloat *params ); -typedef void (*_glGetIntegerv)( GLenum pname, GLint *params ); -typedef void (*_glEndList)( void ); - - -// GLX symbols - should be in the GL lib as well -typedef XVisualInfo* (*_glXChooseVisual)(Display *dpy, int screen, int *attribList); -typedef GLXContext (*_glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); -typedef GLXPixmap (*_glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap); -typedef void (*_glXDestroyContext)(Display *dpy, GLXContext ctx); -typedef void (*_glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix); -typedef const char* (*_glXGetClientString)(Display *dpy, int name ); -typedef int (*_glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value); -typedef Bool (*_glXIsDirect)(Display *dpy, GLXContext ctx); -typedef Bool (*_glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); -typedef Bool (*_glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase); -typedef const char* (*_glXQueryExtensionsString)(Display *dpy, int screen); -typedef const char* (*_glXQueryServerString)(Display *dpy, int screen, int name); -typedef void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable); -typedef void (*_glXUseXFont)(Font font, int first, int count, int listBase); -typedef void (*_glXWaitX)(void); - -extern _glCallLists qt_glCallLists; -extern _glClearColor qt_glClearColor; -extern _glClearIndex qt_glClearIndex; -extern _glColor3ub qt_glColor3ub; -extern _glDeleteLists qt_glDeleteLists; -extern _glDrawBuffer qt_glDrawBuffer; -extern _glFlush qt_glFlush; -extern _glIndexi qt_glIndexi; -extern _glListBase qt_glListBase; -extern _glLoadIdentity qt_glLoadIdentity; -extern _glMatrixMode qt_glMatrixMode; -extern _glOrtho qt_glOrtho; -extern _glPopAttrib qt_glPopAttrib; -extern _glPopMatrix qt_glPopMatrix; -extern _glPushAttrib qt_glPushAttrib; -extern _glPushMatrix qt_glPushMatrix; -extern _glRasterPos2i qt_glRasterPos2i; -extern _glRasterPos3d qt_glRasterPos3d; -extern _glReadPixels qt_glReadPixels; -extern _glViewport qt_glViewport; -extern _glPixelStorei qt_glPixelStorei; -extern _glBitmap qt_glBitmap; -extern _glDrawPixels qt_glDrawPixels; -extern _glNewList qt_glNewList; -extern _glGetFloatv qt_glGetFloatv; -extern _glGetIntegerv qt_glGetIntegerv; -extern _glEndList qt_glEndList; - -extern _glXChooseVisual qt_glXChooseVisual; -extern _glXCreateContext qt_glXCreateContext; -extern _glXCreateGLXPixmap qt_glXCreateGLXPixmap; -extern _glXDestroyContext qt_glXDestroyContext; -extern _glXDestroyGLXPixmap qt_glXDestroyGLXPixmap; -extern _glXGetClientString qt_glXGetClientString; -extern _glXGetConfig qt_glXGetConfig; -extern _glXIsDirect qt_glXIsDirect; -extern _glXMakeCurrent qt_glXMakeCurrent; -extern _glXQueryExtension qt_glXQueryExtension; -extern _glXQueryExtensionsString qt_glXQueryExtensionsString; -extern _glXQueryServerString qt_glXQueryServerString; -extern _glXSwapBuffers qt_glXSwapBuffers; -extern _glXUseXFont qt_glXUseXFont; -extern _glXWaitX qt_glXWaitX; -}; // extern "C" - -#define glCallLists qt_glCallLists -#define glClearColor qt_glClearColor -#define glClearIndex qt_glClearIndex -#define glColor3ub qt_glColor3ub -#define glDeleteLists qt_glDeleteLists -#define glDrawBuffer qt_glDrawBuffer -#define glFlush qt_glFlush -#define glIndexi qt_glIndexi -#define glListBase qt_glListBase -#define glLoadIdentity qt_glLoadIdentity -#define glMatrixMode qt_glMatrixMode -#define glOrtho qt_glOrtho -#define glPopAttrib qt_glPopAttrib -#define glPopMatrix qt_glPopMatrix -#define glPushAttrib qt_glPushAttrib -#define glPushMatrix qt_glPushMatrix -#define glRasterPos2i qt_glRasterPos2i -#define glRasterPos3d qt_glRasterPos3d -#define glReadPixels qt_glReadPixels -#define glViewport qt_glViewport -#define glPixelStorei qt_glPixelStorei -#define glBitmap qt_glBitmap -#define glDrawPixels qt_glDrawPixels -#define glNewList qt_glNewList -#define glGetFloatv qt_glGetFloatv -#define glGetIntegerv qt_glGetIntegerv -#define glEndList qt_glEndList - -#define glXChooseVisual qt_glXChooseVisual -#define glXCreateContext qt_glXCreateContext -#define glXCreateGLXPixmap qt_glXCreateGLXPixmap -#define glXDestroyContext qt_glXDestroyContext -#define glXDestroyGLXPixmap qt_glXDestroyGLXPixmap -#define glXGetClientString qt_glXGetClientString -#define glXGetConfig qt_glXGetConfig -#define glXIsDirect qt_glXIsDirect -#define glXMakeCurrent qt_glXMakeCurrent -#define glXQueryExtension qt_glXQueryExtension -#define glXQueryExtensionsString qt_glXQueryExtensionsString -#define glXQueryServerString qt_glXQueryServerString -#define glXSwapBuffers qt_glXSwapBuffers -#define glXUseXFont qt_glXUseXFont -#define glXWaitX qt_glXWaitX - -#else -inline bool qt_resolve_gl_symbols(bool = TRUE) { return TRUE; } -#endif // QT_DLOPEN_OPENGL -#endif // TQGL_P_H diff --git a/src/opengl/qglcolormap.cpp b/src/opengl/qglcolormap.cpp deleted file mode 100644 index 088c83030..000000000 --- a/src/opengl/qglcolormap.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQGLColormap class -** -** Created : 20010326 -** -** 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. -** -**********************************************************************/ - -/*! - \class TQGLColormap ntqglcolormap.h - \brief The TQGLColormap class is used for installing custom colormaps into - TQGLWidgets. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module OpenGL - \ingroup graphics - \ingroup images - - TQGLColormap provides a platform independent way of specifying and - installing indexed colormaps into TQGLWidgets. TQGLColormap is - especially useful when using the \link opengl.html OpenGL\endlink - color-index mode. - - Under X11 you must use an X server that supports either a \c - PseudoColor or \c DirectColor visual class. If your X server - currently only provides a \c GrayScale, \c TrueColor, \c - StaticColor or \c StaticGray visual, you will not be able to - allocate colorcells for writing. If this is the case, try setting - your X server to 8 bit mode. It should then provide you with at - least a \c PseudoColor visual. Note that you may experience - colormap flashing if your X server is running in 8 bit mode. - - Under Windows the size of the colormap is always set to 256 - colors. Note that under Windows you can also install colormaps - in child widgets. - - This class uses explicit sharing (see \link shclass.html Shared - Classes\endlink). - - Example of use: - \code - #include - #include - - int main() - { - TQApplication a( argc, argv ); - - MySuperGLWidget widget( 0 ); // A TQGLWidget in color-index mode - TQGLColormap colormap; - - // This will fill the colormap with colors ranging from - // black to white. - for ( int i = 0; i < colormap.size(); i++ ) - colormap.setEntry( i, tqRgb( i, i, i ) ); - - widget.setColormap( colormap ); - widget.show(); - return a.exec(); - } - \endcode - - \sa TQGLWidget::setColormap(), TQGLWidget::colormap() -*/ - -#include "ntqglcolormap.h" -#include "tqmemarray.h" - - -/*! - Construct a TQGLColormap. -*/ -TQGLColormap::TQGLColormap() -{ - d = 0; -} - - -/*! - Construct a shallow copy of \a map. -*/ -TQGLColormap::TQGLColormap( const TQGLColormap & map ) -{ - d = map.d; - if ( d ) - d->ref(); -} - -/*! - Dereferences the TQGLColormap and deletes it if this was the last - reference to it. -*/ -TQGLColormap::~TQGLColormap() -{ - if ( d && d->deref() ) { - delete d; - d = 0; - } -} - -/*! - Assign a shallow copy of \a map to this TQGLColormap. -*/ -TQGLColormap & TQGLColormap::operator=( const TQGLColormap & map ) -{ - if ( map.d != 0 ) - map.d->ref(); - - if ( d && d->deref() ) - delete d; - d = map.d; - - return *this; -} - -/*! - Detaches this TQGLColormap from the shared block. -*/ -void TQGLColormap::detach() -{ - if ( d && d->count != 1 ) { - // ### What about the actual colormap handle? - Private * newd = new Private(); - newd->cells = d->cells; - newd->cells.detach(); - if ( d->deref() ) - delete d; - d = newd; - } -} - -/*! - Set cell at index \a idx in the colormap to color \a color. -*/ -void TQGLColormap::setEntry( int idx, TQRgb color ) -{ - if ( !d ) - d = new Private(); - -#if defined(QT_CHECK_RANGE) - if ( idx < 0 || idx > (int) d->cells.size() ) { - tqWarning( "TQGLColormap::setRgb: Index out of range." ); - return; - } -#endif - d->cells[ idx ] = color; -} - -/*! - Set an array of cells in this colormap. \a count is the number of - colors that should be set, \a colors is the array of colors, and - \a base is the starting index. -*/ -void TQGLColormap::setEntries( int count, const TQRgb * colors, int base ) -{ - if ( !d ) - d = new Private(); - - if ( !colors || base < 0 || base >= (int) d->cells.size() ) - return; - - for( int i = base; i < base + count; i++ ) { - if ( i < (int) d->cells.size() ) - setEntry( i, colors[i] ); - else - break; - } -} - -/*! - Returns the TQRgb value in the colorcell with index \a idx. -*/ -TQRgb TQGLColormap::entryRgb( int idx ) const -{ - if ( !d || idx < 0 || idx > (int) d->cells.size() ) - return 0; - else - return d->cells[ idx ]; -} - -/*! - \overload - - Set the cell with index \a idx in the colormap to color \a color. -*/ -void TQGLColormap::setEntry( int idx, const TQColor & color ) -{ - setEntry( idx, color.rgb() ); -} - -/*! - Returns the TQRgb value in the colorcell with index \a idx. -*/ -TQColor TQGLColormap::entryColor( int idx ) const -{ - if ( !d || idx < 0 || idx > (int) d->cells.size() ) - return TQColor(); - else - return TQColor( d->cells[ idx ] ); -} - -/*! - Returns TRUE if the colormap is empty; otherwise returns FALSE. A - colormap with no color values set is considered to be empty. -*/ -bool TQGLColormap::isEmpty() const -{ - return (d == 0) || (d->cells.size() == 0) || (d->cmapHandle == 0); -} - - -/*! - Returns the number of colorcells in the colormap. -*/ -int TQGLColormap::size() const -{ - return d != 0 ? d->cells.size() : 0; -} - -/*! - Returns the index of the color \a color. If \a color is not in the - map, -1 is returned. -*/ -int TQGLColormap::find( TQRgb color ) const -{ - if ( d ) - return d->cells.find( color ); - return -1; -} - -/*! - Returns the index of the color that is the closest match to color - \a color. -*/ -int TQGLColormap::findNearest( TQRgb color ) const -{ - int idx = find( color ); - if ( idx >= 0 ) - return idx; - int mapSize = size(); - int mindist = 200000; - int r = tqRed( color ); - int g = tqGreen( color ); - int b = tqBlue( color ); - int rx, gx, bx, dist; - for ( int i=0; i < mapSize; i++ ) { - TQRgb ci = d->cells[i]; - rx = r - tqRed( ci ); - gx = g - tqGreen( ci ); - bx = b - tqBlue( ci ); - dist = rx*rx + gx*gx + bx*bx; // calculate distance - if ( dist < mindist ) { // minimal? - mindist = dist; - idx = i; - } - } - return idx; -} diff --git a/src/opengl/qt_opengl.pri b/src/opengl/qt_opengl.pri index b0c34887f..79b655422 100644 --- a/src/opengl/qt_opengl.pri +++ b/src/opengl/qt_opengl.pri @@ -1,13 +1,13 @@ # TQt opengl module opengl { - HEADERS += $$OPENGL_H/ntqgl.h \ - $$OPENGL_H/ntqglcolormap.h - SOURCES += $$OPENGL_CPP/qgl.cpp \ - $$OPENGL_CPP/qglcolormap.cpp + HEADERS += $$OPENGL_H/tqgl.h \ + $$OPENGL_H/tqglcolormap.h + SOURCES += $$OPENGL_CPP/tqgl.cpp \ + $$OPENGL_CPP/tqglcolormap.cpp x11 { - HEADERS += $$OPENGL_H/qgl_x11_p.h - SOURCES += $$OPENGL_CPP/qgl_x11.cpp + HEADERS += $$OPENGL_H/tqgl_x11_p.h + SOURCES += $$OPENGL_CPP/tqgl_x11.cpp } else:mac:SOURCES += $$OPENGL_CPP/qgl_mac.cpp else:win32:SOURCES += $$OPENGL_CPP/qgl_win.cpp diff --git a/src/opengl/tqgl.cpp b/src/opengl/tqgl.cpp new file mode 100644 index 000000000..1e8edd59a --- /dev/null +++ b/src/opengl/tqgl.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 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 "tqgl.h" +#include "tqpixmap.h" +#include "tqpaintdevicemetrics.h" +#include "tqimage.h" +#include "ntqcleanuphandler.h" +#include "tqptrdict.h" + +static TQGLFormat* qgl_default_format = 0; +static TQGLFormat* qgl_default_overlay_format = 0; + +#if defined(TQ_WS_X11) +#include "private/qt_x11_p.h" +#define INT32 dummy_INT32 +#define INT8 dummy_INT8 +#include +#undef INT32 +#undef INT8 +#include "tqgl_x11_p.h" +#endif + +static TQCleanupHandler qgl_cleanup_format; + + +/*! + \class TQGL tqgl.h + \brief The TQGL class is a namespace for miscellaneous identifiers + in the TQt OpenGL module. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module OpenGL + \ingroup graphics + \ingroup images + + + Normally you can ignore this class. TQGLWidget and the other + OpenGL* 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. + + * OpenGL is a trademark of Silicon Graphics, Inc. in the + United States and other countries. + +*/ + + +/***************************************************************************** + TQGLFormat implementation + *****************************************************************************/ + + +/*! + \class TQGLFormat tqgl.h + \brief The TQGLFormat class specifies the display format of an OpenGL + rendering context. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\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* 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 + + * 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 tqgl.h + \brief The TQGLContext class encapsulates an OpenGL rendering context. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \ingroup graphics + \ingroup images + \module OpenGL + + An OpenGL* 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. + + * 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(TQ_WS_X11) + qt_resolve_gl_symbols(); + gpm = 0; +#endif + setDevice( dev ); +#if defined(TQ_WS_WIN) + dc = 0; + win = 0; + pixelFormatId = 0; + cmap = 0; +#endif +#if defined(TQ_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 tqgl.h + \brief The TQGLWidget class is a widget for rendering OpenGL graphics. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \ingroup graphics + \ingroup images + \mainclass + \module OpenGL + + TQGLWidget provides functionality for displaying OpenGL* + 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. + + * 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 displayListCache; +}; + +static TQPtrDict * qgl_d_ptr = 0; +static TQSingleCleanupHandler< TQPtrDict > qgl_cleanup_d_ptr; + +static TQGLWidgetPrivate * qgl_d( const TQGLWidget * w ) +{ + if ( !qgl_d_ptr ) { + qgl_d_ptr = new TQPtrDict; + 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(TQ_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( TQ_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(TQ_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(TQ_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(TQ_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( TQ_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 (TQ_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( TQ_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 // TQT_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 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* 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/}. + + +* 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 +*/ diff --git a/src/opengl/tqgl.h b/src/opengl/tqgl.h new file mode 100644 index 000000000..53bdd0e5a --- /dev/null +++ b/src/opengl/tqgl.h @@ -0,0 +1,541 @@ +/**************************************************************************** +** +** Definition 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. +** +**********************************************************************/ + +#ifndef TQGL_H +#define TQGL_H + +#ifndef QT_H +#include "tqwidget.h" +#include "tqglcolormap.h" +#endif // QT_H + +#if !defined( TQT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL ) +#define TQM_EXPORT_OPENGL +#else +#define TQM_EXPORT_OPENGL TQ_EXPORT +#endif + +#ifndef TQT_NO_COMPAT +#define TQGL_VERSION 450 +#define TQGL_VERSION_STR "4.5" +TQM_EXPORT_OPENGL inline const char *qGLVersion() { + tqObsolete( 0, "qGLVersion", "qVersion" ); + return TQGL_VERSION_STR; +} +#endif + +#if defined(TQ_WS_WIN) +# include "qt_windows.h" +#endif + +#if defined(TQ_WS_MAC) +#if !defined( TQMAC_OPENGL_DOUBLEBUFFER ) +/* This macro is different now. If the macro is not defined TQGLWidget will + * try to determine when you need double buffering. If set to 0 it will + * never double buffer and *can* be acclerated. If set to 1 (the default) + * it will always double buffer. Unlike before the value of this macro does + * not upset binary compatability either. */ +#if QT_MACOSX_VERSION >= 0x1020 +# define TQMAC_OPENGL_DOUBLEBUFFER 0 +#endif +#endif +# include +# include +#else +# include +# include +#endif + +#if defined(TQ_WS_WIN) || defined(TQ_WS_MAC) +class TQGLCmap; +#endif + +class TQPixmap; +#if defined(TQ_WS_X11) +class TQGLOverlayWidget; +#endif + +// Namespace class: +class TQM_EXPORT_OPENGL TQGL +{ +public: + enum FormatOption { + DoubleBuffer = 0x0001, + DepthBuffer = 0x0002, + Rgba = 0x0004, + AlphaChannel = 0x0008, + AccumBuffer = 0x0010, + StencilBuffer = 0x0020, + StereoBuffers = 0x0040, + DirectRendering = 0x0080, + HasOverlay = 0x0100, + SingleBuffer = DoubleBuffer << 16, + NoDepthBuffer = DepthBuffer << 16, + ColorIndex = Rgba << 16, + NoAlphaChannel = AlphaChannel << 16, + NoAccumBuffer = AccumBuffer << 16, + NoStencilBuffer = StencilBuffer << 16, + NoStereoBuffers = StereoBuffers << 16, + IndirectRendering = DirectRendering << 16, + NoOverlay = HasOverlay << 16 + }; +}; + + + +class TQM_EXPORT_OPENGL TQGLFormat : public TQGL +{ +public: + TQGLFormat(); + TQGLFormat( int options, int plane = 0 ); + + bool doubleBuffer() const; + void setDoubleBuffer( bool enable ); + bool depth() const; + void setDepth( bool enable ); + bool rgba() const; + void setRgba( bool enable ); + bool alpha() const; + void setAlpha( bool enable ); + bool accum() const; + void setAccum( bool enable ); + bool stencil() const; + void setStencil( bool enable ); + bool stereo() const; + void setStereo( bool enable ); + bool directRendering() const; + void setDirectRendering( bool enable ); + bool hasOverlay() const; + void setOverlay( bool enable ); + + int plane() const; + void setPlane( int plane ); + + void setOption( FormatOption opt ); + bool testOption( FormatOption opt ) const; + + static TQGLFormat defaultFormat(); + static void setDefaultFormat( const TQGLFormat& f ); + + static TQGLFormat defaultOverlayFormat(); + static void setDefaultOverlayFormat( const TQGLFormat& f ); + + static bool hasOpenGL(); + static bool hasOpenGLOverlays(); + + friend TQM_EXPORT_OPENGL bool operator==( const TQGLFormat&, + const TQGLFormat& ); + friend TQM_EXPORT_OPENGL bool operator!=( const TQGLFormat&, + const TQGLFormat& ); +private: + uint opts; + int pln; +}; + + +TQM_EXPORT_OPENGL bool operator==( const TQGLFormat&, const TQGLFormat& ); +TQM_EXPORT_OPENGL bool operator!=( const TQGLFormat&, const TQGLFormat& ); + +class TQM_EXPORT_OPENGL TQGLContext : public TQGL +{ +public: + TQGLContext( const TQGLFormat& format, TQPaintDevice* device ); + TQGLContext( const TQGLFormat& format ); + virtual ~TQGLContext(); + + virtual bool create( const TQGLContext* shareContext = 0 ); + bool isValid() const; + bool isSharing() const; + virtual void reset(); + + TQGLFormat format() const; + TQGLFormat requestedFormat() const; + virtual void setFormat( const TQGLFormat& format ); + + virtual void makeCurrent(); + virtual void swapBuffers() const; + + TQPaintDevice* device() const; + + TQColor overlayTransparentColor() const; + + static const TQGLContext* currentContext(); + +protected: + virtual bool chooseContext( const TQGLContext* shareContext = 0 ); + virtual void doneCurrent(); // ### 4.0: make this public - needed for multithreading stuff + +#if defined(TQ_WS_WIN) + virtual int choosePixelFormat( void* pfd, HDC pdc ); +#endif +#if defined(TQ_WS_X11) + virtual void* tryVisual( const TQGLFormat& f, int bufDepth = 1 ); + virtual void* chooseVisual(); +#endif +#if defined(TQ_WS_MAC) + virtual void* chooseMacVisual(GDHandle); +#endif + + bool deviceIsPixmap() const; + bool windowCreated() const; + void setWindowCreated( bool on ); + bool initialized() const; + void setInitialized( bool on ); + void generateFontDisplayLists( const TQFont & fnt, int listBase ); + + uint colorIndex( const TQColor& c ) const; + void setValid( bool valid ); + void setDevice( TQPaintDevice *pDev ); + +protected: +#if defined(TQ_WS_WIN) + HGLRC rc; + HDC dc; + WId win; + int pixelFormatId; + TQGLCmap* cmap; +#elif defined(TQ_WS_X11) || defined(TQ_WS_MAC) + void* vi; + void* cx; +#if defined(TQ_WS_X11) + TQ_UINT32 gpm; +#endif +#endif + TQGLFormat glFormat; + TQGLFormat reqFormat; + static TQGLContext* currentCtx; + +private: + void init( TQPaintDevice *dev = 0 ); + class Private { + public: + bool valid; + bool sharing; + bool initDone; + bool crWin; + TQPaintDevice* paintDevice; + TQColor transpColor; +#ifdef TQ_WS_MAC + TQRect oldR; +#endif + }; + Private* d; + + friend class TQGLWidget; +#ifdef TQ_WS_MAC + void fixBufferRect(); +#endif + +private: // Disabled copy constructor and operator= + TQGLContext() {} + TQGLContext( const TQGLContext& ) {} + TQGLContext& operator=( const TQGLContext& ) { return *this; } +}; + + + + +class TQM_EXPORT_OPENGL TQGLWidget : public TQWidget, public TQGL +{ + TQ_OBJECT +public: + TQGLWidget( TQWidget* parent=0, const char* name=0, + const TQGLWidget* shareWidget = 0, WFlags f=0 ); + TQGLWidget( TQGLContext *context, TQWidget* parent, const char* name=0, + const TQGLWidget* shareWidget = 0, WFlags f=0 ); + TQGLWidget( const TQGLFormat& format, TQWidget* parent=0, const char* name=0, + const TQGLWidget* shareWidget = 0, WFlags f=0 ); + ~TQGLWidget(); + + void qglColor( const TQColor& c ) const; + void qglClearColor( const TQColor& c ) const; + + bool isValid() const; + bool isSharing() const; + virtual void makeCurrent(); + void doneCurrent(); + + bool doubleBuffer() const; + virtual void swapBuffers(); + + TQGLFormat format() const; +#ifndef Q_QDOC + virtual void setFormat( const TQGLFormat& format ); +#endif + + const TQGLContext* context() const; +#ifndef Q_QDOC + virtual void setContext( TQGLContext* context, + const TQGLContext* shareContext = 0, + bool deleteOldContext = TRUE ); +#endif + + virtual TQPixmap renderPixmap( int w = 0, int h = 0, + bool useContext = FALSE ); + virtual TQImage grabFrameBuffer( bool withAlpha = FALSE ); + + virtual void makeOverlayCurrent(); + const TQGLContext* overlayContext() const; + + static TQImage convertToGLFormat( const TQImage& img ); + + void setMouseTracking( bool enable ); + virtual void reparent( TQWidget* parent, WFlags f, const TQPoint& p, + bool showIt = FALSE ); + + const TQGLColormap & colormap() const; + void setColormap( const TQGLColormap & map ); + + void renderText( int x, int y, const TQString & str, + const TQFont & fnt = TQFont(), int listBase = 2000 ); + void renderText( double x, double y, double z, const TQString & str, + const TQFont & fnt = TQFont(), int listBase = 2000 ); +public slots: + virtual void updateGL(); + virtual void updateOverlayGL(); + +protected: + virtual void initializeGL(); + virtual void resizeGL( int w, int h ); + virtual void paintGL(); + + virtual void initializeOverlayGL(); + virtual void resizeOverlayGL( int w, int h ); + virtual void paintOverlayGL(); + + void setAutoBufferSwap( bool on ); + bool autoBufferSwap() const; + + void paintEvent( TQPaintEvent* ); + void resizeEvent( TQResizeEvent* ); + + virtual void glInit(); + virtual void glDraw(); + +private: + int displayListBase( const TQFont & fnt, int listBase ); + void cleanupColormaps(); + void init( TQGLContext *context, const TQGLWidget* shareWidget ); + bool renderCxPm( TQPixmap* pm ); + TQGLContext* glcx; + bool autoSwap; + + TQGLColormap cmap; + +#if defined(TQ_WS_WIN) || defined(TQ_WS_MAC) + TQGLContext* olcx; +#elif defined(TQ_WS_X11) + TQGLOverlayWidget* olw; + friend class TQGLOverlayWidget; +#endif + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQGLWidget( const TQGLWidget& ); + TQGLWidget& operator=( const TQGLWidget& ); +#endif + +#if defined(TQ_WS_MAC) +private: + const TQGLContext *slcx; + uint pending_fix : 1, + glcx_dblbuf : 2, + dblbuf : 1, + clp_serial : 15; + TQPixmap *gl_pix; + TQGLFormat req_format; + + void macInternalRecreateContext( TQGLContext *ctx, + const TQGLContext* = NULL, + bool update = TRUE ); + bool macInternalDoubleBuffer( bool fix = TRUE ); + virtual void setRegionDirty( bool ); + virtual void macWidgetChangedWindow(); +#endif +private slots: + void macInternalFixBufferRect(); +}; + + +// +// TQGLFormat inline functions +// + +inline bool TQGLFormat::doubleBuffer() const +{ + return testOption( DoubleBuffer ); +} + +inline bool TQGLFormat::depth() const +{ + return testOption( DepthBuffer ); +} + +inline bool TQGLFormat::rgba() const +{ + return testOption( Rgba ); +} + +inline bool TQGLFormat::alpha() const +{ + return testOption( AlphaChannel ); +} + +inline bool TQGLFormat::accum() const +{ + return testOption( AccumBuffer ); +} + +inline bool TQGLFormat::stencil() const +{ + return testOption( StencilBuffer ); +} + +inline bool TQGLFormat::stereo() const +{ + return testOption( StereoBuffers ); +} + +inline bool TQGLFormat::directRendering() const +{ + return testOption( DirectRendering ); +} + +inline bool TQGLFormat::hasOverlay() const +{ + return testOption( HasOverlay ); +} + +// +// TQGLContext inline functions +// + +inline bool TQGLContext::isValid() const +{ + return d->valid; +} + +inline void TQGLContext::setValid( bool valid ) +{ + d->valid = valid; +} + +inline bool TQGLContext::isSharing() const +{ + return d->sharing; +} + +inline TQGLFormat TQGLContext::format() const +{ + return glFormat; +} + +inline TQGLFormat TQGLContext::requestedFormat() const +{ + return reqFormat; +} + +inline TQPaintDevice* TQGLContext::device() const +{ + return d->paintDevice; +} + +inline bool TQGLContext::deviceIsPixmap() const +{ + return d->paintDevice->devType() == TQInternal::Pixmap; +} + + +inline bool TQGLContext::windowCreated() const +{ + return d->crWin; +} + + +inline void TQGLContext::setWindowCreated( bool on ) +{ + d->crWin = on; +} + +inline bool TQGLContext::initialized() const +{ + return d->initDone; +} + +inline void TQGLContext::setInitialized( bool on ) +{ + d->initDone = on; +} + +inline const TQGLContext* TQGLContext::currentContext() +{ + return currentCtx; +} + +// +// TQGLWidget inline functions +// + +inline TQGLFormat TQGLWidget::format() const +{ + return glcx->format(); +} + +inline const TQGLContext *TQGLWidget::context() const +{ + return glcx; +} + +inline bool TQGLWidget::doubleBuffer() const +{ + return glcx->format().doubleBuffer(); +} + +inline void TQGLWidget::setAutoBufferSwap( bool on ) +{ + autoSwap = on; +} + +inline bool TQGLWidget::autoBufferSwap() const +{ + return autoSwap; +} + +#endif diff --git a/src/opengl/tqgl_x11.cpp b/src/opengl/tqgl_x11.cpp new file mode 100644 index 000000000..e3fdfc504 --- /dev/null +++ b/src/opengl/tqgl_x11.cpp @@ -0,0 +1,1406 @@ +/**************************************************************************** +** +** 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 "tqgl.h" + +#if defined(TQ_WS_X11) + +#include "tqmap.h" +#include "tqpixmap.h" +#include "ntqapplication.h" + +#include "tqintdict.h" +#include "private/tqfontengine_p.h" + +#define INT8 dummy_INT8 +#define INT32 dummy_INT32 +#include +#undef INT8 +#undef INT32 +#include +#include +#include +#include + +// POSIX Large File Support redefines truncate -> truncate64 +#if defined(truncate) +# undef truncate +#endif + +#ifndef QT_DLOPEN_OPENGL +extern "C" { + Status XmuLookupStandardColormap( Display *dpy, int screen, VisualID visualid, + unsigned int depth, Atom property, + Bool replace, Bool retain ); +} +#endif + +#include "tqgl_x11_p.h" +#ifdef QT_DLOPEN_OPENGL +#include "ntqlibrary.h" + +extern "C" { +_glCallLists qt_glCallLists; +_glClearColor qt_glClearColor; +_glClearIndex qt_glClearIndex; +_glColor3ub qt_glColor3ub; +_glDeleteLists qt_glDeleteLists; +_glDrawBuffer qt_glDrawBuffer; +_glFlush qt_glFlush; +_glIndexi qt_glIndexi; +_glListBase qt_glListBase; +_glLoadIdentity qt_glLoadIdentity; +_glMatrixMode qt_glMatrixMode; +_glOrtho qt_glOrtho; +_glPopAttrib qt_glPopAttrib; +_glPopMatrix qt_glPopMatrix; +_glPushAttrib qt_glPushAttrib; +_glPushMatrix qt_glPushMatrix; +_glRasterPos2i qt_glRasterPos2i; +_glRasterPos3d qt_glRasterPos3d; +_glReadPixels qt_glReadPixels; +_glViewport qt_glViewport; +_glPixelStorei qt_glPixelStorei; +_glBitmap qt_glBitmap; +_glDrawPixels qt_glDrawPixels; +_glNewList qt_glNewList; +_glGetFloatv qt_glGetFloatv; +_glGetIntegerv qt_glGetIntegerv; +_glEndList qt_glEndList; + +_glXChooseVisual qt_glXChooseVisual; +_glXCreateContext qt_glXCreateContext; +_glXCreateGLXPixmap qt_glXCreateGLXPixmap; +_glXDestroyContext qt_glXDestroyContext; +_glXDestroyGLXPixmap qt_glXDestroyGLXPixmap; +_glXGetClientString qt_glXGetClientString; +_glXGetConfig qt_glXGetConfig; +_glXIsDirect qt_glXIsDirect; +_glXMakeCurrent qt_glXMakeCurrent; +_glXQueryExtension qt_glXQueryExtension; +_glXQueryExtensionsString qt_glXQueryExtensionsString; +_glXQueryServerString qt_glXQueryServerString; +_glXSwapBuffers qt_glXSwapBuffers; +_glXUseXFont qt_glXUseXFont; +_glXWaitX qt_glXWaitX; +}; + +bool qt_resolve_gl_symbols(bool fatal) +{ + static bool gl_syms_resolved = FALSE; + if (gl_syms_resolved) + return TRUE; + + TQLibrary gl("GL.so.1"); + gl.setAutoUnload(FALSE); + + qt_glCallLists = (_glCallLists) gl.resolve("glCallLists"); + + if (!qt_glCallLists) { // if this fails the rest will surely fail + if (fatal) + tqFatal("Unable to resolve GL/GLX symbols - please check your GL library installation."); + return FALSE; + } + + qt_glClearColor = (_glClearColor) gl.resolve("glClearColor"); + qt_glClearIndex = (_glClearIndex) gl.resolve("glClearIndex"); + qt_glColor3ub = (_glColor3ub) gl.resolve("glColor3ub"); + qt_glDeleteLists = (_glDeleteLists) gl.resolve("glDeleteLists"); + qt_glDrawBuffer = (_glDrawBuffer) gl.resolve("glDrawBuffer"); + qt_glFlush = (_glFlush) gl.resolve("glFlush"); + qt_glIndexi = (_glIndexi) gl.resolve("glIndexi"); + qt_glListBase = (_glListBase) gl.resolve("glListBase"); + qt_glLoadIdentity = (_glLoadIdentity) gl.resolve("glLoadIdentity"); + qt_glMatrixMode = (_glMatrixMode) gl.resolve("glMatrixMode"); + qt_glOrtho = (_glOrtho) gl.resolve("glOrtho"); + qt_glPopAttrib = (_glPopAttrib) gl.resolve("glPopAttrib"); + qt_glPopMatrix = (_glPopMatrix) gl.resolve("glPopMatrix"); + qt_glPushAttrib = (_glPushAttrib) gl.resolve("glPushAttrib"); + qt_glPushMatrix = (_glPushMatrix) gl.resolve("glPushMatrix"); + qt_glRasterPos2i = (_glRasterPos2i) gl.resolve("glRasterPos2i"); + qt_glRasterPos3d = (_glRasterPos3d) gl.resolve("glRasterPos3d"); + qt_glReadPixels = (_glReadPixels) gl.resolve("glReadPixels"); + qt_glViewport = (_glViewport) gl.resolve("glViewport"); + qt_glPixelStorei = (_glPixelStorei) gl.resolve("glPixelStorei"); + qt_glBitmap = (_glBitmap) gl.resolve("glBitmap"); + qt_glDrawPixels = (_glDrawPixels) gl.resolve("glDrawPixels"); + qt_glNewList = (_glNewList) gl.resolve("glNewList"); + qt_glGetFloatv = (_glGetFloatv) gl.resolve("glGetFloatv"); + qt_glGetIntegerv = (_glGetIntegerv) gl.resolve("glGetIntegerv"); + qt_glEndList = (_glEndList) gl.resolve("glEndList"); + + qt_glXChooseVisual = (_glXChooseVisual) gl.resolve("glXChooseVisual"); + qt_glXCreateContext = (_glXCreateContext) gl.resolve("glXCreateContext"); + qt_glXCreateGLXPixmap = (_glXCreateGLXPixmap) gl.resolve("glXCreateGLXPixmap"); + qt_glXDestroyContext = (_glXDestroyContext) gl.resolve("glXDestroyContext"); + qt_glXDestroyGLXPixmap = (_glXDestroyGLXPixmap) gl.resolve("glXDestroyGLXPixmap"); + qt_glXGetClientString = (_glXGetClientString) gl.resolve("glXGetClientString"); + qt_glXGetConfig = (_glXGetConfig) gl.resolve("glXGetConfig"); + qt_glXIsDirect = (_glXIsDirect) gl.resolve("glXIsDirect"); + qt_glXMakeCurrent = (_glXMakeCurrent) gl.resolve("glXMakeCurrent"); + qt_glXQueryExtension = (_glXQueryExtension) gl.resolve("glXQueryExtension"); + qt_glXQueryExtensionsString = (_glXQueryExtensionsString) gl.resolve("glXQueryExtensionsString"); + qt_glXQueryServerString = (_glXQueryServerString) gl.resolve("glXQueryServerString"); + qt_glXSwapBuffers = (_glXSwapBuffers) gl.resolve("glXSwapBuffers"); + qt_glXUseXFont = (_glXUseXFont) gl.resolve("glXUseXFont"); + qt_glXWaitX = (_glXWaitX) gl.resolve("glXWaitX"); + gl_syms_resolved = TRUE; + return TRUE; +} +#endif // QT_DLOPEN_OPENGL + + +/* + The choose_cmap function is internal and used by TQGLWidget::setContext() + and GLX (not Windows). If the application can't find any sharable + colormaps, it must at least create as few colormaps as possible. The + dictionary solution below ensures only one colormap is created per visual. + Colormaps are also deleted when the application terminates. +*/ + +struct CMapEntry { + CMapEntry(); + ~CMapEntry(); + Colormap cmap; + bool alloc; + XStandardColormap scmap; +}; + +CMapEntry::CMapEntry() +{ + cmap = 0; + alloc = FALSE; + scmap.colormap = 0; +} + +CMapEntry::~CMapEntry() +{ + if ( alloc ) + XFreeColormap( TQPaintDevice::x11AppDisplay(), cmap ); +} + +static TQIntDict *cmap_dict = 0; +static bool mesa_gl = FALSE; +static TQIntDict< TQMap > *qglcmap_dict = 0; + +static void cleanup_cmaps() +{ + if (cmap_dict) { + cmap_dict->setAutoDelete(TRUE); + delete cmap_dict; + cmap_dict = 0; + } + if (qglcmap_dict) { + qglcmap_dict->setAutoDelete(TRUE); + delete qglcmap_dict; + qglcmap_dict = 0; + } +} + +static Colormap choose_cmap( Display *dpy, XVisualInfo *vi ) +{ + if ( !cmap_dict ) { + cmap_dict = new TQIntDict; + const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION ); + if ( v ) + mesa_gl = strstr(v,"Mesa") != 0; + tqAddPostRoutine( cleanup_cmaps ); + } + + CMapEntry *x = cmap_dict->find( (long) vi->visualid + ( vi->screen * 256 ) ); + if ( x ) // found colormap for visual + return x->cmap; + + x = new CMapEntry(); + + XStandardColormap *c; + int n, i; + + // tqDebug( "Choosing cmap for vID %0x", vi->visualid ); + + if ( vi->visualid == + XVisualIDFromVisual( (Visual*)TQPaintDevice::x11AppVisual( vi->screen ) ) ) { + // tqDebug( "Using x11AppColormap" ); + return TQPaintDevice::x11AppColormap( vi->screen ); + } + + if ( mesa_gl ) { // we're using MesaGL + Atom hp_cmaps = XInternAtom( dpy, "_HP_RGB_SMOOTH_MAP_LIST", TRUE ); + if ( hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8 ) { + if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, + hp_cmaps) ) { + i = 0; + while ( i < n && x->cmap == 0 ) { + if ( c[i].visualid == vi->visual->visualid ) { + x->cmap = c[i].colormap; + x->scmap = c[i]; + //tqDebug( "Using HP_RGB scmap" ); + + } + i++; + } + XFree( (char *)c ); + } + } + } +#if !defined(Q_OS_SOLARIS) + if ( !x->cmap ) { +#ifdef QT_DLOPEN_OPENGL + typedef Status (*_XmuLookupStandardColormap)( Display *dpy, int screen, VisualID visualid, unsigned int depth, + Atom property, Bool replace, Bool retain ); + _XmuLookupStandardColormap qt_XmuLookupStandardColormap; + qt_XmuLookupStandardColormap = (_XmuLookupStandardColormap) TQLibrary::resolve("Xmu.so.6", "XmuLookupStandardColormap"); + if (!qt_XmuLookupStandardColormap) + tqFatal("Unable to resolve Xmu symbols - please check your Xmu library installation."); +#define XmuLookupStandardColormap qt_XmuLookupStandardColormap + +#endif + + if ( XmuLookupStandardColormap(dpy,vi->screen,vi->visualid,vi->depth, + XA_RGB_DEFAULT_MAP,FALSE,TRUE) ) { + if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n, + XA_RGB_DEFAULT_MAP) ) { + i = 0; + while ( i < n && x->cmap == 0 ) { + if ( c[i].visualid == vi->visualid ) { + x->cmap = c[i].colormap; + x->scmap = c[i]; + //tqDebug( "Using RGB_DEFAULT scmap" ); + } + i++; + } + XFree( (char *)c ); + } + } + } +#endif + if ( !x->cmap ) { // no shared cmap found + x->cmap = XCreateColormap( dpy, RootWindow(dpy,vi->screen), vi->visual, + AllocNone ); + x->alloc = TRUE; + // tqDebug( "Allocating cmap" ); + } + + // associate cmap with visualid + cmap_dict->insert( (long) vi->visualid + ( vi->screen * 256 ), x ); + return x->cmap; +} + +struct TransColor +{ + VisualID vis; + int screen; + long color; +}; + +static TQMemArray trans_colors; +static int trans_colors_init = FALSE; + + +static void find_trans_colors() +{ + struct OverlayProp { + long visual; + long type; + long value; + long layer; + }; + + trans_colors_init = TRUE; + + Display* appDisplay = TQPaintDevice::x11AppDisplay(); + + int scr; + int lastsize = 0; + for ( scr = 0; scr < ScreenCount( appDisplay ); scr++ ) { + TQWidget* rootWin = TQApplication::desktop()->screen( scr ); + if ( !rootWin ) + return; // Should not happen + Atom overlayVisualsAtom = XInternAtom( appDisplay, + "SERVER_OVERLAY_VISUALS", True ); + if ( overlayVisualsAtom == None ) + return; // Server has no overlays + + Atom actualType; + int actualFormat; + ulong nItems; + ulong bytesAfter; + OverlayProp* overlayProps = 0; + int res = XGetWindowProperty( appDisplay, rootWin->winId(), + overlayVisualsAtom, 0, 10000, False, + overlayVisualsAtom, &actualType, + &actualFormat, &nItems, &bytesAfter, + (uchar**)&overlayProps ); + + if ( res != Success || actualType != overlayVisualsAtom + || actualFormat != 32 || nItems < 4 || !overlayProps ) + return; // Error reading property + + int numProps = nItems / 4; + trans_colors.resize( lastsize + numProps ); + int j = lastsize; + for ( int i = 0; i < numProps; i++ ) { + if ( overlayProps[i].type == 1 ) { + trans_colors[j].vis = (VisualID)overlayProps[i].visual; + trans_colors[j].screen = scr; + trans_colors[j].color = (int)overlayProps[i].value; + j++; + } + } + XFree( overlayProps ); + lastsize = j; + trans_colors.truncate( lastsize ); + } +} + + +/***************************************************************************** + TQGLFormat UNIX/GLX-specific code + *****************************************************************************/ + +bool TQGLFormat::hasOpenGL() +{ + if (!qt_resolve_gl_symbols(FALSE)) + return FALSE; + return glXQueryExtension(tqt_xdisplay(),0,0) != 0; +} + + +bool TQGLFormat::hasOpenGLOverlays() +{ + qt_resolve_gl_symbols(); + if ( !trans_colors_init ) + find_trans_colors(); + return trans_colors.size() > 0; +} + + + +/***************************************************************************** + TQGLContext UNIX/GLX-specific code + *****************************************************************************/ + +bool TQGLContext::chooseContext( const TQGLContext* shareContext ) +{ + Display* disp = d->paintDevice->x11Display(); + vi = chooseVisual(); + if ( !vi ) + return FALSE; + + if ( deviceIsPixmap() && + (((XVisualInfo*)vi)->depth != d->paintDevice->x11Depth() || + ((XVisualInfo*)vi)->screen != d->paintDevice->x11Screen()) ) + { + XFree( vi ); + XVisualInfo appVisInfo; + memset( &appVisInfo, 0, sizeof(XVisualInfo) ); + appVisInfo.visualid = XVisualIDFromVisual( (Visual*)d->paintDevice->x11Visual() ); + appVisInfo.screen = d->paintDevice->x11Screen(); + int nvis; + vi = XGetVisualInfo( disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis ); + if ( !vi ) + return FALSE; + + int useGL; + glXGetConfig( disp, (XVisualInfo*)vi, GLX_USE_GL, &useGL ); + if ( !useGL ) + return FALSE; //# Chickening out already... + } + int res; + glXGetConfig( disp, (XVisualInfo*)vi, GLX_LEVEL, &res ); + glFormat.setPlane( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_DOUBLEBUFFER, &res ); + glFormat.setDoubleBuffer( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_DEPTH_SIZE, &res ); + glFormat.setDepth( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_RGBA, &res ); + glFormat.setRgba( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_ALPHA_SIZE, &res ); + glFormat.setAlpha( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_ACCUM_RED_SIZE, &res ); + glFormat.setAccum( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_STENCIL_SIZE, &res ); + glFormat.setStencil( res ); + glXGetConfig( disp, (XVisualInfo*)vi, GLX_STEREO, &res ); + glFormat.setStereo( res ); + + Bool direct = format().directRendering() ? True : False; + + if ( shareContext && + ( !shareContext->isValid() || !shareContext->cx ) ) { +#if defined(QT_CHECK_NULL) + tqWarning("TQGLContext::chooseContext(): Cannot share with invalid context"); +#endif + shareContext = 0; + } + + // 1. Sharing between rgba and color-index will give wrong colors. + // 2. Contexts cannot be shared btw. direct/non-direct renderers. + // 3. Pixmaps cannot share contexts that are set up for direct rendering. + if ( shareContext && (format().rgba() != shareContext->format().rgba() || + (deviceIsPixmap() && + glXIsDirect( disp, (GLXContext)shareContext->cx )))) + shareContext = 0; + + cx = 0; + if ( shareContext ) { + cx = glXCreateContext( disp, (XVisualInfo *)vi, + (GLXContext)shareContext->cx, direct ); + if ( cx ) + d->sharing = TRUE; + } + if ( !cx ) + cx = glXCreateContext( disp, (XVisualInfo *)vi, None, direct ); + if ( !cx ) + return FALSE; + glFormat.setDirectRendering( glXIsDirect( disp, (GLXContext)cx ) ); + if ( deviceIsPixmap() ) { +#if defined(GLX_MESA_pixmap_colormap) && defined(TQGL_USE_MESA_EXT) + gpm = glXCreateGLXPixmapMESA( disp, (XVisualInfo *)vi, + d->paintDevice->handle(), + choose_cmap( disp, (XVisualInfo *)vi ) ); +#else + gpm = (TQ_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi, + d->paintDevice->handle() ); +#endif + if ( !gpm ) + return FALSE; + } + return TRUE; +} + + +/*! + X11 only: This virtual function tries to find a + visual that matches the format, reducing the demands if the original + request cannot be met. + + The algorithm for reducing the demands of the format is quite + simple-minded, so override this method in your subclass if your + application has spcific requirements on visual selection. + + \sa chooseContext() +*/ + +void *TQGLContext::chooseVisual() +{ + static int bufDepths[] = { 8, 4, 2, 1 }; // Try 16, 12 also? + //todo: if pixmap, also make sure that vi->depth == pixmap->depth + void* vis = 0; + int i = 0; + bool fail = FALSE; + TQGLFormat fmt = format(); + bool tryDouble = !fmt.doubleBuffer(); // Some GL impl's only have double + bool triedDouble = FALSE; + while( !fail && !( vis = tryVisual( fmt, bufDepths[i] ) ) ) { + if ( !fmt.rgba() && bufDepths[i] > 1 ) { + i++; + continue; + } + if ( tryDouble ) { + fmt.setDoubleBuffer( TRUE ); + tryDouble = FALSE; + triedDouble = TRUE; + continue; + } + else if ( triedDouble ) { + fmt.setDoubleBuffer( FALSE ); + triedDouble = FALSE; + } + if ( fmt.stereo() ) { + fmt.setStereo( FALSE ); + continue; + } + if ( fmt.accum() ) { + fmt.setAccum( FALSE ); + continue; + } + if ( fmt.stencil() ) { + fmt.setStencil( FALSE ); + continue; + } + if ( fmt.alpha() ) { + fmt.setAlpha( FALSE ); + continue; + } + if ( fmt.depth() ) { + fmt.setDepth( FALSE ); + continue; + } + if ( fmt.doubleBuffer() ) { + fmt.setDoubleBuffer( FALSE ); + continue; + } + fail = TRUE; + } + glFormat = fmt; + return vis; +} + + +/*! + + \internal + + X11 only: This virtual function chooses a visual + that matches the OpenGL \link format() format\endlink. Reimplement this + function in a subclass if you need a custom visual. + + \sa chooseContext() +*/ + +void *TQGLContext::tryVisual( const TQGLFormat& f, int bufDepth ) +{ + int spec[40]; + int i = 0; + spec[i++] = GLX_LEVEL; + spec[i++] = f.plane(); + +#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) + static bool useTranspExt = FALSE; + static bool useTranspExtChecked = FALSE; + if ( f.plane() && !useTranspExtChecked && d->paintDevice ) { + TQCString estr( glXQueryExtensionsString( d->paintDevice->x11Display(), + d->paintDevice->x11Screen() ) ); + useTranspExt = estr.contains( "GLX_EXT_visual_info" ); + //# (A bit simplistic; that could theoretically be a substring) + if ( useTranspExt ) { + TQCString cstr( glXGetClientString( d->paintDevice->x11Display(), + GLX_VENDOR ) ); + useTranspExt = !cstr.contains( "Xi Graphics" ); // bug workaround + if ( useTranspExt ) { + // bug workaround - some systems (eg. FireGL) refuses to return an overlay + // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specfied, even if + // the implementation supports transparent overlays + int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, + f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, + None }; + XVisualInfo * vinf = glXChooseVisual( d->paintDevice->x11Display(), + d->paintDevice->x11Screen(), tmpSpec ); + if ( !vinf ) { + useTranspExt = FALSE; + } + } + } + + useTranspExtChecked = TRUE; + } + if ( f.plane() && useTranspExt ) { + // Required to avoid non-transparent overlay visual(!) on some systems + spec[i++] = GLX_TRANSPARENT_TYPE_EXT; + spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; + } +#endif + + if ( f.doubleBuffer() ) + spec[i++] = GLX_DOUBLEBUFFER; + if ( f.depth() ) { + spec[i++] = GLX_DEPTH_SIZE; + spec[i++] = 1; + } + if ( f.stereo() ) { + spec[i++] = GLX_STEREO; + } + if ( f.stencil() ) { + spec[i++] = GLX_STENCIL_SIZE; + spec[i++] = 1; + } + if ( f.rgba() ) { + spec[i++] = GLX_RGBA; + spec[i++] = GLX_RED_SIZE; + spec[i++] = 1; + spec[i++] = GLX_GREEN_SIZE; + spec[i++] = 1; + spec[i++] = GLX_BLUE_SIZE; + spec[i++] = 1; + if ( f.alpha() ) { + spec[i++] = GLX_ALPHA_SIZE; + spec[i++] = 1; + } + if ( f.accum() ) { + spec[i++] = GLX_ACCUM_RED_SIZE; + spec[i++] = 1; + spec[i++] = GLX_ACCUM_GREEN_SIZE; + spec[i++] = 1; + spec[i++] = GLX_ACCUM_BLUE_SIZE; + spec[i++] = 1; + if ( f.alpha() ) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; + spec[i++] = 1; + } + } + } + else { + spec[i++] = GLX_BUFFER_SIZE; + spec[i++] = bufDepth; + } + + spec[i] = None; + return glXChooseVisual( d->paintDevice->x11Display(), + d->paintDevice->x11Screen(), spec ); +} + + +void TQGLContext::reset() +{ + if ( !d->valid ) + return; + doneCurrent(); + if ( gpm ) + glXDestroyGLXPixmap( d->paintDevice->x11Display(), (GLXPixmap)gpm ); + gpm = 0; + glXDestroyContext( d->paintDevice->x11Display(), (GLXContext)cx ); + if ( vi ) + XFree( vi ); + vi = 0; + cx = 0; + d->crWin = FALSE; + d->sharing = FALSE; + d->valid = FALSE; + d->transpColor = TQColor(); + d->initDone = FALSE; +} + + +void TQGLContext::makeCurrent() +{ + if ( !d->valid ) { +#if defined(QT_CHECK_STATE) + tqWarning("TQGLContext::makeCurrent(): Cannot make invalid context current."); +#endif + return; + } + bool ok = TRUE; + if ( deviceIsPixmap() ) + ok = glXMakeCurrent( d->paintDevice->x11Display(), + (GLXPixmap)gpm, + (GLXContext)cx ); + + else + ok = glXMakeCurrent( d->paintDevice->x11Display(), + ((TQWidget *)d->paintDevice)->winId(), + (GLXContext)cx ); +#if defined(QT_CHECK_NULL) + // tqDebug("makeCurrent: %i, vi=%i, vi->vi=%i, vi->id=%i", (int)this, (int)vi, (int)((XVisualInfo*)vi)->visual, (int)((XVisualInfo*)vi)->visualid ); + if ( !ok ) + tqWarning("TQGLContext::makeCurrent(): Failed."); +#endif + if ( ok ) + currentCtx = this; +} + +void TQGLContext::doneCurrent() +{ + glXMakeCurrent( d->paintDevice->x11Display(), 0, 0 ); + currentCtx = 0; +} + + +void TQGLContext::swapBuffers() const +{ + if ( !d->valid ) + return; + if ( !deviceIsPixmap() ) + glXSwapBuffers( d->paintDevice->x11Display(), + ((TQWidget *)d->paintDevice)->winId() ); +} + +TQColor TQGLContext::overlayTransparentColor() const +{ + //### make more efficient using the transpColor member + if ( isValid() ) { + if ( !trans_colors_init ) + find_trans_colors(); + + VisualID myVisualId = ((XVisualInfo*)vi)->visualid; + int myScreen = ((XVisualInfo*)vi)->screen; + for ( int i = 0; i < (int)trans_colors.size(); i++ ) { + if ( trans_colors[i].vis == myVisualId && + trans_colors[i].screen == myScreen ) { + XColor col; + col.pixel = trans_colors[i].color; + col.red = col.green = col.blue = 0; + col.flags = 0; + Display *dpy = d->paintDevice->x11Display(); + if (col.pixel > (uint) ((XVisualInfo *)vi)->colormap_size - 1) + col.pixel = ((XVisualInfo *)vi)->colormap_size - 1; + XQueryColor(dpy, choose_cmap(dpy, (XVisualInfo *) vi), &col); + uchar r = (uchar)((col.red / 65535.0) * 255.0 + 0.5); + uchar g = (uchar)((col.green / 65535.0) * 255.0 + 0.5); + uchar b = (uchar)((col.blue / 65535.0) * 255.0 + 0.5); + return TQColor(tqRgb(r,g,b), trans_colors[i].color); + } + } + } + return TQColor(); // Invalid color +} + + +uint TQGLContext::colorIndex( const TQColor& c ) const +{ + int screen = ((XVisualInfo *)vi)->screen; + if ( isValid() ) { + if ( format().plane() + && c.pixel( screen ) == overlayTransparentColor().pixel( screen ) ) + return c.pixel( screen ); // Special; don't look-up + if ( ((XVisualInfo*)vi)->visualid == + XVisualIDFromVisual( (Visual*)TQPaintDevice::x11AppVisual( screen ) ) ) + return c.pixel( screen ); // We're using TQColor's cmap + + XVisualInfo *info = (XVisualInfo *) vi; + CMapEntry *x = cmap_dict->find( (long) info->visualid + ( info->screen * 256 ) ); + if ( x && !x->alloc) { // It's a standard colormap + int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0); + int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0); + int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0); + uint p = x->scmap.base_pixel + + ( rf * x->scmap.red_mult ) + + ( gf * x->scmap.green_mult ) + + ( bf * x->scmap.blue_mult ); + return p; + } else { + if (!qglcmap_dict) { + qglcmap_dict = new TQIntDict< TQMap >; + } + TQMap *cmap; + if ((cmap = qglcmap_dict->find((long) info->visualid)) == 0) { + cmap = new TQMap; + qglcmap_dict->insert((long) info->visualid, cmap); + } + + // already in the map? + TQRgb target = c.rgb(); + TQMap::Iterator it = cmap->begin(); + for (; it != cmap->end(); ++it) { + if ((*it) == target) + return it.key(); + } + + // need to alloc color + unsigned long plane_mask[2]; + unsigned long color_map_entry; + if (!XAllocColorCells (TQPaintDevice::x11AppDisplay(), x->cmap, TRUE, plane_mask, 0, + &color_map_entry, 1)) + return c.pixel(screen); + + XColor col; + col.flags = DoRed | DoGreen | DoBlue; + col.pixel = color_map_entry; + col.red = (ushort)((tqRed(c.rgb()) / 255.0) * 65535.0 + 0.5); + col.green = (ushort)((tqGreen(c.rgb()) / 255.0) * 65535.0 + 0.5); + col.blue = (ushort)((tqBlue(c.rgb()) / 255.0) * 65535.0 + 0.5); + XStoreColor(TQPaintDevice::x11AppDisplay(), x->cmap, &col); + + cmap->insert(color_map_entry, target); + return color_map_entry; + } + } + return 0; +} + +#ifndef TQT_NO_XFTFREETYPE +/*! \internal + This is basically a substitute for glxUseXFont() which can only + handle XLFD fonts. This version relies on XFT v2 to render the + glyphs, but it works with all fonts that XFT2 provides - both + antialiased and aliased bitmap and outline fonts. +*/ +void qgl_use_font(TQFontEngineXft *engine, int first, int count, int listBase) +{ + GLfloat color[4]; + glGetFloatv(GL_CURRENT_COLOR, color); + + // save the pixel unpack state + GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; + glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); + glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); + glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); + glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); + glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); + glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); + + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + Bool antialiased = False; +#if 0 // disable antialias support for now + XftPatternGetBool(engine->pattern(), XFT_ANTIALIAS, 0, &antialiased); +#endif +#ifdef QT_XFT2 + FT_Face face = XftLockFace(engine->font()); +#else + FT_Face face = engine->face(); +#endif + // start generating font glyphs + for (int i = first; i < count; ++i) { + int list = listBase + i; + GLfloat x0, y0, dx, dy; + + FT_Error err; + + err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); + if (err) { + tqDebug("failed loading glyph %d from font", i); + Q_ASSERT(!err); + } + err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal + : ft_render_mode_mono)); + if (err) { + tqDebug("failed rendering glyph %d from font", i); + Q_ASSERT(!err); + } + + FT_Bitmap bm = face->glyph->bitmap; + x0 = face->glyph->metrics.horiBearingX >> 6; + y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; + dx = face->glyph->metrics.horiAdvance >> 6; + dy = 0; + int sz = bm.pitch * bm.rows; + uint *aa_glyph = 0; + uchar *ua_glyph = 0; + + if (antialiased) + aa_glyph = new uint[sz]; + else + ua_glyph = new uchar[sz]; + + // convert to GL format + for (int y = 0; y < bm.rows; ++y) { + for (int x = 0; x < bm.pitch; ++x) { + int c1 = y*bm.pitch + x; + int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; + if (antialiased) { + aa_glyph[c1] = (int(color[0]*255) << 24) + | (int(color[1]*255) << 16) + | (int(color[2]*255) << 8) | bm.buffer[c2]; + } else { + ua_glyph[c1] = bm.buffer[c2]; + } + } + } + + glNewList(list, GL_COMPILE); + if (antialiased) { + // calling glBitmap() is just a trick to move the current + // raster pos, since glGet*() won't work in display lists + glBitmap(0, 0, 0, 0, x0, -y0, 0); + glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); + glBitmap(0, 0, 0, 0, dx-x0, y0, 0); + } else { + glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); + } + glEndList(); + antialiased ? delete[] aa_glyph : delete[] ua_glyph; + } + +#ifdef QT_XFT2 + XftUnlockFace(engine->font()); +#endif + + // restore pixel unpack settings + glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); +} +#endif + +void TQGLContext::generateFontDisplayLists( const TQFont & fnt, int listBase ) +{ + TQFont f(fnt); + TQFontEngine *engine = f.d->engineForScript(TQFont::Latin); + +#ifndef TQT_NO_XFTFREETYPE + if(engine->type() == TQFontEngine::Xft) { + qgl_use_font((TQFontEngineXft *) engine, 0, 256, listBase); + return; + } +#endif + // glXUseXFont() only works with XLFD font structures and a few GL + // drivers crash if 0 is passed as the font handle + f.setStyleStrategy(TQFont::OpenGLCompatible); + if (f.handle() && (engine->type() == TQFontEngine::XLFD + || engine->type() == TQFontEngine::LatinXLFD)) { + glXUseXFont((Font) f.handle(), 0, 256, listBase); + } +} + +/***************************************************************************** + TQGLOverlayWidget (Internal overlay class for X11) + *****************************************************************************/ + +class TQGLOverlayWidget : public TQGLWidget +{ + TQ_OBJECT +public: + TQGLOverlayWidget( const TQGLFormat& format, TQGLWidget* parent, + const char* name=0, const TQGLWidget* shareWidget=0 ); + +protected: + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + +private: + TQGLWidget* realWidget; + +private: // Disabled copy constructor and operator= +#if defined(TQ_DISABLE_COPY) + TQGLOverlayWidget( const TQGLOverlayWidget& ); + TQGLOverlayWidget& operator=( const TQGLOverlayWidget& ); +#endif +}; + + +TQGLOverlayWidget::TQGLOverlayWidget( const TQGLFormat& format, TQGLWidget* parent, + const char* name, + const TQGLWidget* shareWidget ) + : TQGLWidget( format, parent, name, shareWidget ? shareWidget->olw : 0 ) +{ + realWidget = parent; +} + + + +void TQGLOverlayWidget::initializeGL() +{ + TQColor transparentColor = context()->overlayTransparentColor(); + if ( transparentColor.isValid() ) + qglClearColor( transparentColor ); + else + tqWarning( "TQGLOverlayWidget::initializeGL(): Could not get transparent color" ); + realWidget->initializeOverlayGL(); +} + + +void TQGLOverlayWidget::resizeGL( int w, int h ) +{ + glViewport( 0, 0, w, h ); + realWidget->resizeOverlayGL( w, h ); +} + + +void TQGLOverlayWidget::paintGL() +{ + realWidget->paintOverlayGL(); +} + +#undef Bool +#include "tqgl_x11.moc" + +/***************************************************************************** + TQGLWidget UNIX/GLX-specific code + *****************************************************************************/ +void TQGLWidget::init( TQGLContext *context, const TQGLWidget *shareWidget ) +{ + qt_resolve_gl_symbols(); + + glcx = 0; + olw = 0; + autoSwap = TRUE; + if ( !context->device() ) + context->setDevice( this ); + + if ( shareWidget ) + setContext( context, shareWidget->context() ); + else + setContext( context ); + setBackgroundMode( NoBackground ); + + if ( isValid() && context->format().hasOverlay() ) { + TQCString olwName( name() ); + olwName += "-TQGL_internal_overlay_widget"; + olw = new TQGLOverlayWidget( TQGLFormat::defaultOverlayFormat(), + this, olwName, shareWidget ); + if ( olw->isValid() ) { + olw->setAutoBufferSwap( FALSE ); + olw->setFocusProxy( this ); + } + else { + delete olw; + olw = 0; + glcx->glFormat.setOverlay( FALSE ); + } + } +} + +/*! \reimp */ +void TQGLWidget::reparent( TQWidget* parent, WFlags f, const TQPoint& p, + bool showIt ) +{ + if (glcx) + glcx->doneCurrent(); + TQWidget::reparent( parent, f, p, FALSE ); + if ( showIt ) + show(); +} + + +void TQGLWidget::setMouseTracking( bool enable ) +{ + if ( olw ) + olw->setMouseTracking( enable ); + TQWidget::setMouseTracking( enable ); +} + + +void TQGLWidget::resizeEvent( TQResizeEvent * ) +{ + if ( !isValid() ) + return; + makeCurrent(); + if ( !glcx->initialized() ) + glInit(); + glXWaitX(); + resizeGL( width(), height() ); + if ( olw ) + olw->setGeometry( rect() ); +} + +const TQGLContext* TQGLWidget::overlayContext() const +{ + if ( olw ) + return olw->context(); + else + return 0; +} + + +void TQGLWidget::makeOverlayCurrent() +{ + if ( olw ) + olw->makeCurrent(); +} + + +void TQGLWidget::updateOverlayGL() +{ + if ( olw ) + olw->updateGL(); +} + +void TQGLWidget::setContext( TQGLContext *context, + const TQGLContext* shareContext, + bool deleteOldContext ) +{ + if ( context == 0 ) { +#if defined(QT_CHECK_NULL) + tqWarning( "TQGLWidget::setContext: Cannot set null context" ); +#endif + return; + } + if ( !context->deviceIsPixmap() && context->device() != this ) { +#if defined(QT_CHECK_STATE) + tqWarning( "TQGLWidget::setContext: Context must refer to this widget" ); +#endif + return; + } + + if ( glcx ) + glcx->doneCurrent(); + TQGLContext* oldcx = glcx; + glcx = context; + + bool createFailed = FALSE; + if ( !glcx->isValid() ) { + if ( !glcx->create( shareContext ? shareContext : oldcx ) ) + createFailed = TRUE; + } + if ( createFailed ) { + if ( deleteOldContext ) + delete oldcx; + return; + } + + if ( glcx->windowCreated() || glcx->deviceIsPixmap() ) { + if ( deleteOldContext ) + delete oldcx; + return; + } + + bool visible = isVisible(); + if ( visible ) + hide(); + + XVisualInfo *vi = (XVisualInfo*)glcx->vi; + XSetWindowAttributes a; + + a.colormap = choose_cmap( x11Display(), vi ); // find best colormap + a.background_pixel = backgroundColor().pixel( vi->screen ); + a.border_pixel = black.pixel( vi->screen ); + Window p = RootWindow( x11Display(), vi->screen ); + if ( parentWidget() ) + p = parentWidget()->winId(); + + Window w = XCreateWindow( x11Display(), p, x(), y(), width(), height(), + 0, vi->depth, InputOutput, vi->visual, + CWBackPixel|CWBorderPixel|CWColormap, &a ); + + Window *cmw; + Window *cmwret; + int count; + if ( XGetWMColormapWindows( x11Display(), topLevelWidget()->winId(), + &cmwret, &count ) ) { + cmw = new Window[count+1]; + memcpy( (char *)cmw, (char *)cmwret, sizeof(Window)*count ); + XFree( (char *)cmwret ); + int i; + for ( i=0; i= count ) // append new window + cmw[count++] = w; + } else { + count = 1; + cmw = new Window[count]; + cmw[0] = w; + } + +#if defined(GLX_MESA_release_buffers) && defined(TQGL_USE_MESA_EXT) + if ( oldcx && oldcx->windowCreated() ) + glXReleaseBuffersMESA( x11Display(), winId() ); +#endif + if ( deleteOldContext ) + delete oldcx; + oldcx = 0; + + create( w ); + + XSetWMColormapWindows( x11Display(), topLevelWidget()->winId(), cmw, + count ); + delete [] cmw; + + if ( visible ) + show(); + XFlush( x11Display() ); + glcx->setWindowCreated( TRUE ); +} + + +bool TQGLWidget::renderCxPm( TQPixmap* pm ) +{ + if ( ((XVisualInfo*)glcx->vi)->depth != pm->depth() ) + return FALSE; + + GLXPixmap glPm; +#if defined(GLX_MESA_pixmap_colormap) && defined(TQGL_USE_MESA_EXT) + glPm = glXCreateGLXPixmapMESA( x11Display(), + (XVisualInfo*)glcx->vi, + (Pixmap)pm->handle(), + choose_cmap( pm->x11Display(), + (XVisualInfo*)glcx->vi ) ); +#else + glPm = (TQ_UINT32)glXCreateGLXPixmap( x11Display(), + (XVisualInfo*)glcx->vi, + (Pixmap)pm->handle() ); +#endif + + if ( !glXMakeCurrent( x11Display(), glPm, (GLXContext)glcx->cx ) ) { + glXDestroyGLXPixmap( x11Display(), glPm ); + return FALSE; + } + + glDrawBuffer( GL_FRONT ); + if ( !glcx->initialized() ) + glInit(); + resizeGL( pm->width(), pm->height() ); + paintGL(); + glFlush(); + makeCurrent(); + glXDestroyGLXPixmap( x11Display(), glPm ); + resizeGL( width(), height() ); + return TRUE; +} + +const TQGLColormap & TQGLWidget::colormap() const +{ + return cmap; +} + +/*\internal + Store color values in the given colormap. +*/ +static void qStoreColors( TQWidget * tlw, Colormap cmap, + const TQGLColormap & cols ) +{ + XColor c; + TQRgb color; + + for ( int i = 0; i < cols.size(); i++ ) { + color = cols.entryRgb( i ); + c.pixel = i; + c.red = (ushort)( (tqRed( color ) / 255.0) * 65535.0 + 0.5 ); + c.green = (ushort)( (tqGreen( color ) / 255.0) * 65535.0 + 0.5 ); + c.blue = (ushort)( (tqBlue( color ) / 255.0) * 65535.0 + 0.5 ); + c.flags = DoRed | DoGreen | DoBlue; + XStoreColor( tlw->x11Display(), cmap, &c ); + } +} + +/*\internal + Check whether the given visual supports dynamic colormaps or not. +*/ +static bool qCanAllocColors( TQWidget * w ) +{ + bool validVisual = FALSE; + int numVisuals; + long mask; + XVisualInfo templ; + XVisualInfo * visuals; + VisualID id = XVisualIDFromVisual( (Visual *) + w->topLevelWidget()->x11Visual() ); + + mask = VisualScreenMask; + templ.screen = w->x11Screen(); + visuals = XGetVisualInfo( w->x11Display(), mask, &templ, &numVisuals ); + + for ( int i = 0; i < numVisuals; i++ ) { + if ( visuals[i].visualid == id ) { + switch ( visuals[i].c_class ) { + case TrueColor: + case StaticColor: + case StaticGray: + case GrayScale: + validVisual = FALSE; + break; + case DirectColor: + case PseudoColor: + validVisual = TRUE; + break; + } + break; + } + } + XFree( visuals ); + + if ( !validVisual ) + return FALSE; + return TRUE; +} + +void TQGLWidget::setColormap( const TQGLColormap & c ) +{ + TQWidget * tlw = topLevelWidget(); // must return a valid widget + + cmap = c; + if ( !cmap.d ) + return; + + if ( !cmap.d->cmapHandle && !qCanAllocColors( this ) ) { + tqWarning( "TQGLWidget::setColormap: Cannot create a read/write " + "colormap for this visual" ); + return; + } + + // If the child GL widget is not of the same visual class as the + // toplevel widget we will get in trouble.. + Window wid = tlw->winId(); + Visual * vis = (Visual *) tlw->x11Visual();; + VisualID cvId = XVisualIDFromVisual( (Visual *) x11Visual() ); + VisualID tvId = XVisualIDFromVisual( (Visual *) tlw->x11Visual() ); + if ( cvId != tvId ) { + wid = winId(); + vis = (Visual *) x11Visual(); + } + + if ( !cmap.d->cmapHandle ) // allocate a cmap if necessary + cmap.d->cmapHandle = XCreateColormap( x11Display(), wid, vis, + AllocAll ); + + qStoreColors( this, (Colormap) cmap.d->cmapHandle, c ); + XSetWindowColormap( x11Display(), wid, (Colormap) cmap.d->cmapHandle ); + + // tell the wm that this window has a special colormap + Window * cmw; + Window * cmwret; + int count; + if ( XGetWMColormapWindows( x11Display(), tlw->winId(), &cmwret, + &count ) ) + { + cmw = new Window[count+1]; + memcpy( (char *) cmw, (char *) cmwret, sizeof(Window) * count ); + XFree( (char *) cmwret ); + int i; + for ( i = 0; i < count; i++ ) { + if ( cmw[i] == winId() ) { + break; + } + } + if ( i >= count ) // append new window only if not in the list + cmw[count++] = winId(); + } else { + count = 1; + cmw = new Window[count]; + cmw[0] = winId(); + } + XSetWMColormapWindows( x11Display(), tlw->winId(), cmw, count ); + delete [] cmw; +} + +/*! \internal + Free up any allocated colormaps. This fn is only called for + top-level widgets. +*/ +void TQGLWidget::cleanupColormaps() +{ + if ( !cmap.d ) + return; + + if ( cmap.d->cmapHandle ) { + XFreeColormap( topLevelWidget()->x11Display(), + (Colormap) cmap.d->cmapHandle ); + cmap.d->cmapHandle = 0; + } +} + +void TQGLWidget::macInternalFixBufferRect() +{ +} + +#endif diff --git a/src/opengl/tqgl_x11_p.h b/src/opengl/tqgl_x11_p.h new file mode 100644 index 000000000..cbcd741b9 --- /dev/null +++ b/src/opengl/tqgl_x11_p.h @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Definitions needed for resolving GL/GLX symbols using dlopen() +** under X11. +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of the OpenGL module of the 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. +** +** 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. +** +**********************************************************************/ + +#ifndef TQGL_P_H +#define TQGL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the TQt API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifdef QT_DLOPEN_OPENGL +// resolve the GL symbols we use ourselves +bool qt_resolve_gl_symbols(bool = TRUE); +extern "C" { +// GL symbols +typedef void (*_glCallLists)( GLsizei n, GLenum type, const GLvoid *lists ); +typedef void (*_glClearColor)( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ); +typedef void (*_glClearIndex)( GLfloat c ); +typedef void (*_glColor3ub)( GLubyte red, GLubyte green, GLubyte blue ); +typedef void (*_glDeleteLists)( GLuint list, GLsizei range ); +typedef void (*_glDrawBuffer)( GLenum mode ); +typedef void (*_glFlush)( void ); +typedef void (*_glIndexi)( GLint c ); +typedef void (*_glListBase)( GLuint base ); +typedef void (*_glLoadIdentity)( void ); +typedef void (*_glMatrixMode)( GLenum mode ); +typedef void (*_glOrtho)( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val ); +typedef void (*_glPopAttrib)( void ); +typedef void (*_glPopMatrix)( void ); +typedef void (*_glPushAttrib)( GLbitfield mask ); +typedef void (*_glPushMatrix)( void ); +typedef void (*_glRasterPos2i)( GLint x, GLint y ); +typedef void (*_glRasterPos3d)( GLdouble x, GLdouble y, GLdouble z ); +typedef void (*_glReadPixels)( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); +typedef void (*_glViewport)( GLint x, GLint y, GLsizei width, GLsizei height ); +typedef void (*_glPixelStorei)( GLenum pname, GLint param ); +typedef void (*_glBitmap)( GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap ); +typedef void (*_glDrawPixels)( GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels ); +typedef void (*_glNewList)( GLuint list, GLenum mode ); +typedef void (*_glGetFloatv)( GLenum pname, GLfloat *params ); +typedef void (*_glGetIntegerv)( GLenum pname, GLint *params ); +typedef void (*_glEndList)( void ); + + +// GLX symbols - should be in the GL lib as well +typedef XVisualInfo* (*_glXChooseVisual)(Display *dpy, int screen, int *attribList); +typedef GLXContext (*_glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct); +typedef GLXPixmap (*_glXCreateGLXPixmap)(Display *dpy, XVisualInfo *vis, Pixmap pixmap); +typedef void (*_glXDestroyContext)(Display *dpy, GLXContext ctx); +typedef void (*_glXDestroyGLXPixmap)(Display *dpy, GLXPixmap pix); +typedef const char* (*_glXGetClientString)(Display *dpy, int name ); +typedef int (*_glXGetConfig)(Display *dpy, XVisualInfo *vis, int attrib, int *value); +typedef Bool (*_glXIsDirect)(Display *dpy, GLXContext ctx); +typedef Bool (*_glXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); +typedef Bool (*_glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase); +typedef const char* (*_glXQueryExtensionsString)(Display *dpy, int screen); +typedef const char* (*_glXQueryServerString)(Display *dpy, int screen, int name); +typedef void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable); +typedef void (*_glXUseXFont)(Font font, int first, int count, int listBase); +typedef void (*_glXWaitX)(void); + +extern _glCallLists qt_glCallLists; +extern _glClearColor qt_glClearColor; +extern _glClearIndex qt_glClearIndex; +extern _glColor3ub qt_glColor3ub; +extern _glDeleteLists qt_glDeleteLists; +extern _glDrawBuffer qt_glDrawBuffer; +extern _glFlush qt_glFlush; +extern _glIndexi qt_glIndexi; +extern _glListBase qt_glListBase; +extern _glLoadIdentity qt_glLoadIdentity; +extern _glMatrixMode qt_glMatrixMode; +extern _glOrtho qt_glOrtho; +extern _glPopAttrib qt_glPopAttrib; +extern _glPopMatrix qt_glPopMatrix; +extern _glPushAttrib qt_glPushAttrib; +extern _glPushMatrix qt_glPushMatrix; +extern _glRasterPos2i qt_glRasterPos2i; +extern _glRasterPos3d qt_glRasterPos3d; +extern _glReadPixels qt_glReadPixels; +extern _glViewport qt_glViewport; +extern _glPixelStorei qt_glPixelStorei; +extern _glBitmap qt_glBitmap; +extern _glDrawPixels qt_glDrawPixels; +extern _glNewList qt_glNewList; +extern _glGetFloatv qt_glGetFloatv; +extern _glGetIntegerv qt_glGetIntegerv; +extern _glEndList qt_glEndList; + +extern _glXChooseVisual qt_glXChooseVisual; +extern _glXCreateContext qt_glXCreateContext; +extern _glXCreateGLXPixmap qt_glXCreateGLXPixmap; +extern _glXDestroyContext qt_glXDestroyContext; +extern _glXDestroyGLXPixmap qt_glXDestroyGLXPixmap; +extern _glXGetClientString qt_glXGetClientString; +extern _glXGetConfig qt_glXGetConfig; +extern _glXIsDirect qt_glXIsDirect; +extern _glXMakeCurrent qt_glXMakeCurrent; +extern _glXQueryExtension qt_glXQueryExtension; +extern _glXQueryExtensionsString qt_glXQueryExtensionsString; +extern _glXQueryServerString qt_glXQueryServerString; +extern _glXSwapBuffers qt_glXSwapBuffers; +extern _glXUseXFont qt_glXUseXFont; +extern _glXWaitX qt_glXWaitX; +}; // extern "C" + +#define glCallLists qt_glCallLists +#define glClearColor qt_glClearColor +#define glClearIndex qt_glClearIndex +#define glColor3ub qt_glColor3ub +#define glDeleteLists qt_glDeleteLists +#define glDrawBuffer qt_glDrawBuffer +#define glFlush qt_glFlush +#define glIndexi qt_glIndexi +#define glListBase qt_glListBase +#define glLoadIdentity qt_glLoadIdentity +#define glMatrixMode qt_glMatrixMode +#define glOrtho qt_glOrtho +#define glPopAttrib qt_glPopAttrib +#define glPopMatrix qt_glPopMatrix +#define glPushAttrib qt_glPushAttrib +#define glPushMatrix qt_glPushMatrix +#define glRasterPos2i qt_glRasterPos2i +#define glRasterPos3d qt_glRasterPos3d +#define glReadPixels qt_glReadPixels +#define glViewport qt_glViewport +#define glPixelStorei qt_glPixelStorei +#define glBitmap qt_glBitmap +#define glDrawPixels qt_glDrawPixels +#define glNewList qt_glNewList +#define glGetFloatv qt_glGetFloatv +#define glGetIntegerv qt_glGetIntegerv +#define glEndList qt_glEndList + +#define glXChooseVisual qt_glXChooseVisual +#define glXCreateContext qt_glXCreateContext +#define glXCreateGLXPixmap qt_glXCreateGLXPixmap +#define glXDestroyContext qt_glXDestroyContext +#define glXDestroyGLXPixmap qt_glXDestroyGLXPixmap +#define glXGetClientString qt_glXGetClientString +#define glXGetConfig qt_glXGetConfig +#define glXIsDirect qt_glXIsDirect +#define glXMakeCurrent qt_glXMakeCurrent +#define glXQueryExtension qt_glXQueryExtension +#define glXQueryExtensionsString qt_glXQueryExtensionsString +#define glXQueryServerString qt_glXQueryServerString +#define glXSwapBuffers qt_glXSwapBuffers +#define glXUseXFont qt_glXUseXFont +#define glXWaitX qt_glXWaitX + +#else +inline bool qt_resolve_gl_symbols(bool = TRUE) { return TRUE; } +#endif // QT_DLOPEN_OPENGL +#endif // TQGL_P_H diff --git a/src/opengl/tqglcolormap.cpp b/src/opengl/tqglcolormap.cpp new file mode 100644 index 000000000..a9f176b96 --- /dev/null +++ b/src/opengl/tqglcolormap.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Implementation of TQGLColormap class +** +** Created : 20010326 +** +** 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. +** +**********************************************************************/ + +/*! + \class TQGLColormap tqglcolormap.h + \brief The TQGLColormap class is used for installing custom colormaps into + TQGLWidgets. +\if defined(commercial) + It is part of the TQt Enterprise Edition. +\endif + + \module OpenGL + \ingroup graphics + \ingroup images + + TQGLColormap provides a platform independent way of specifying and + installing indexed colormaps into TQGLWidgets. TQGLColormap is + especially useful when using the \link opengl.html OpenGL\endlink + color-index mode. + + Under X11 you must use an X server that supports either a \c + PseudoColor or \c DirectColor visual class. If your X server + currently only provides a \c GrayScale, \c TrueColor, \c + StaticColor or \c StaticGray visual, you will not be able to + allocate colorcells for writing. If this is the case, try setting + your X server to 8 bit mode. It should then provide you with at + least a \c PseudoColor visual. Note that you may experience + colormap flashing if your X server is running in 8 bit mode. + + Under Windows the size of the colormap is always set to 256 + colors. Note that under Windows you can also install colormaps + in child widgets. + + This class uses explicit sharing (see \link shclass.html Shared + Classes\endlink). + + Example of use: + \code + #include + #include + + int main() + { + TQApplication a( argc, argv ); + + MySuperGLWidget widget( 0 ); // A TQGLWidget in color-index mode + TQGLColormap colormap; + + // This will fill the colormap with colors ranging from + // black to white. + for ( int i = 0; i < colormap.size(); i++ ) + colormap.setEntry( i, tqRgb( i, i, i ) ); + + widget.setColormap( colormap ); + widget.show(); + return a.exec(); + } + \endcode + + \sa TQGLWidget::setColormap(), TQGLWidget::colormap() +*/ + +#include "tqglcolormap.h" +#include "tqmemarray.h" + + +/*! + Construct a TQGLColormap. +*/ +TQGLColormap::TQGLColormap() +{ + d = 0; +} + + +/*! + Construct a shallow copy of \a map. +*/ +TQGLColormap::TQGLColormap( const TQGLColormap & map ) +{ + d = map.d; + if ( d ) + d->ref(); +} + +/*! + Dereferences the TQGLColormap and deletes it if this was the last + reference to it. +*/ +TQGLColormap::~TQGLColormap() +{ + if ( d && d->deref() ) { + delete d; + d = 0; + } +} + +/*! + Assign a shallow copy of \a map to this TQGLColormap. +*/ +TQGLColormap & TQGLColormap::operator=( const TQGLColormap & map ) +{ + if ( map.d != 0 ) + map.d->ref(); + + if ( d && d->deref() ) + delete d; + d = map.d; + + return *this; +} + +/*! + Detaches this TQGLColormap from the shared block. +*/ +void TQGLColormap::detach() +{ + if ( d && d->count != 1 ) { + // ### What about the actual colormap handle? + Private * newd = new Private(); + newd->cells = d->cells; + newd->cells.detach(); + if ( d->deref() ) + delete d; + d = newd; + } +} + +/*! + Set cell at index \a idx in the colormap to color \a color. +*/ +void TQGLColormap::setEntry( int idx, TQRgb color ) +{ + if ( !d ) + d = new Private(); + +#if defined(QT_CHECK_RANGE) + if ( idx < 0 || idx > (int) d->cells.size() ) { + tqWarning( "TQGLColormap::setRgb: Index out of range." ); + return; + } +#endif + d->cells[ idx ] = color; +} + +/*! + Set an array of cells in this colormap. \a count is the number of + colors that should be set, \a colors is the array of colors, and + \a base is the starting index. +*/ +void TQGLColormap::setEntries( int count, const TQRgb * colors, int base ) +{ + if ( !d ) + d = new Private(); + + if ( !colors || base < 0 || base >= (int) d->cells.size() ) + return; + + for( int i = base; i < base + count; i++ ) { + if ( i < (int) d->cells.size() ) + setEntry( i, colors[i] ); + else + break; + } +} + +/*! + Returns the TQRgb value in the colorcell with index \a idx. +*/ +TQRgb TQGLColormap::entryRgb( int idx ) const +{ + if ( !d || idx < 0 || idx > (int) d->cells.size() ) + return 0; + else + return d->cells[ idx ]; +} + +/*! + \overload + + Set the cell with index \a idx in the colormap to color \a color. +*/ +void TQGLColormap::setEntry( int idx, const TQColor & color ) +{ + setEntry( idx, color.rgb() ); +} + +/*! + Returns the TQRgb value in the colorcell with index \a idx. +*/ +TQColor TQGLColormap::entryColor( int idx ) const +{ + if ( !d || idx < 0 || idx > (int) d->cells.size() ) + return TQColor(); + else + return TQColor( d->cells[ idx ] ); +} + +/*! + Returns TRUE if the colormap is empty; otherwise returns FALSE. A + colormap with no color values set is considered to be empty. +*/ +bool TQGLColormap::isEmpty() const +{ + return (d == 0) || (d->cells.size() == 0) || (d->cmapHandle == 0); +} + + +/*! + Returns the number of colorcells in the colormap. +*/ +int TQGLColormap::size() const +{ + return d != 0 ? d->cells.size() : 0; +} + +/*! + Returns the index of the color \a color. If \a color is not in the + map, -1 is returned. +*/ +int TQGLColormap::find( TQRgb color ) const +{ + if ( d ) + return d->cells.find( color ); + return -1; +} + +/*! + Returns the index of the color that is the closest match to color + \a color. +*/ +int TQGLColormap::findNearest( TQRgb color ) const +{ + int idx = find( color ); + if ( idx >= 0 ) + return idx; + int mapSize = size(); + int mindist = 200000; + int r = tqRed( color ); + int g = tqGreen( color ); + int b = tqBlue( color ); + int rx, gx, bx, dist; + for ( int i=0; i < mapSize; i++ ) { + TQRgb ci = d->cells[i]; + rx = r - tqRed( ci ); + gx = g - tqGreen( ci ); + bx = b - tqBlue( ci ); + dist = rx*rx + gx*gx + bx*bx; // calculate distance + if ( dist < mindist ) { // minimal? + mindist = dist; + idx = i; + } + } + return idx; +} diff --git a/src/opengl/tqglcolormap.h b/src/opengl/tqglcolormap.h new file mode 100644 index 000000000..61fbd7c79 --- /dev/null +++ b/src/opengl/tqglcolormap.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Definition of TQGLColormap class +** +** Created : 20010326 +** +** 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. +** +**********************************************************************/ + +#ifndef TQGLCOLORMAP_H +#define TQGLCOLORMAP_H + +#ifndef QT_H +#include "tqcolor.h" +#include "tqmemarray.h" +#include "ntqshared.h" +#endif // QT_H + +#if !defined( TQT_MODULE_OPENGL ) || defined( QT_LICENSE_PROFESSIONAL ) +#define TQM_EXPORT_OPENGL +#else +#define TQM_EXPORT_OPENGL TQ_EXPORT +#endif + +class TQWidget; +class TQM_EXPORT_OPENGL TQGLColormap +{ +public: + TQGLColormap(); + TQGLColormap( const TQGLColormap & ); + ~TQGLColormap(); + + TQGLColormap &operator=( const TQGLColormap & ); + + bool isEmpty() const; + int size() const; + void detach(); + + void setEntries( int count, const TQRgb * colors, int base = 0 ); + void setEntry( int idx, TQRgb color ); + void setEntry( int idx, const TQColor & color ); + TQRgb entryRgb( int idx ) const; + TQColor entryColor( int idx ) const; + int find( TQRgb color ) const; + int findNearest( TQRgb color ) const; + +private: + class Private : public TQShared + { + public: + Private() { + cells.resize( 256 ); // ### hardcoded to 256 entries for now + cmapHandle = 0; + } + + ~Private() { + } + + TQMemArray cells; + TQt::HANDLE cmapHandle; + }; + + Private * d; + + friend class TQGLWidget; +}; + +#endif -- cgit v1.2.3