summaryrefslogtreecommitdiffstats
path: root/src/opengl/qgl_x11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl/qgl_x11.cpp')
-rw-r--r--src/opengl/qgl_x11.cpp1406
1 files changed, 1406 insertions, 0 deletions
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
new file mode 100644
index 000000000..9e58d5244
--- /dev/null
+++ b/src/opengl/qgl_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 retquirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qgl.h"
+
+#if defined(Q_WS_X11)
+
+#include "qmap.h"
+#include "qpixmap.h"
+#include "qapplication.h"
+
+#include "qintdict.h"
+#include "private/qfontengine_p.h"
+
+#define INT8 dummy_INT8
+#define INT32 dummy_INT32
+#include <GL/glx.h>
+#undef INT8
+#undef INT32
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+
+// POSIX Large File Support redefines truncate -> truncate64
+#if defined(truncate)
+# undef truncate
+#endif
+
+#ifndef QT_DLOPEN_OPENGL
+extern "C" {
+ Status XmuLookupStandardColormap( Display *dpy, int screen, VisualID visualid,
+ unsigned int depth, Atom property,
+ Bool replace, Bool retain );
+}
+#endif
+
+#include "qgl_x11_p.h"
+#ifdef QT_DLOPEN_OPENGL
+#include "qlibrary.h"
+
+extern "C" {
+_glCallLists qt_glCallLists;
+_glClearColor qt_glClearColor;
+_glClearIndex qt_glClearIndex;
+_glColor3ub qt_glColor3ub;
+_glDeleteLists qt_glDeleteLists;
+_glDrawBuffer qt_glDrawBuffer;
+_glFlush qt_glFlush;
+_glIndexi qt_glIndexi;
+_glListBase qt_glListBase;
+_glLoadIdentity qt_glLoadIdentity;
+_glMatrixMode qt_glMatrixMode;
+_glOrtho qt_glOrtho;
+_glPopAttrib qt_glPopAttrib;
+_glPopMatrix qt_glPopMatrix;
+_glPushAttrib qt_glPushAttrib;
+_glPushMatrix qt_glPushMatrix;
+_glRasterPos2i qt_glRasterPos2i;
+_glRasterPos3d qt_glRasterPos3d;
+_glReadPixels qt_glReadPixels;
+_glViewport qt_glViewport;
+_glPixelStorei qt_glPixelStorei;
+_glBitmap qt_glBitmap;
+_glDrawPixels qt_glDrawPixels;
+_glNewList qt_glNewList;
+_glGetFloatv qt_glGetFloatv;
+_glGetIntegerv qt_glGetIntegerv;
+_glEndList qt_glEndList;
+
+_glXChooseVisual qt_glXChooseVisual;
+_glXCreateContext qt_glXCreateContext;
+_glXCreateGLXPixmap qt_glXCreateGLXPixmap;
+_glXDestroyContext qt_glXDestroyContext;
+_glXDestroyGLXPixmap qt_glXDestroyGLXPixmap;
+_glXGetClientString qt_glXGetClientString;
+_glXGetConfig qt_glXGetConfig;
+_glXIsDirect qt_glXIsDirect;
+_glXMakeCurrent qt_glXMakeCurrent;
+_glXQueryExtension qt_glXQueryExtension;
+_glXQueryExtensionsString qt_glXQueryExtensionsString;
+_glXQueryServerString qt_glXQueryServerString;
+_glXSwapBuffers qt_glXSwapBuffers;
+_glXUseXFont qt_glXUseXFont;
+_glXWaitX qt_glXWaitX;
+};
+
+bool qt_resolve_gl_symbols(bool fatal)
+{
+ static bool gl_syms_resolved = FALSE;
+ if (gl_syms_resolved)
+ return TRUE;
+
+ 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)
+ qFatal("Unable to resolve GL/GLX symbols - please check your GL library installation.");
+ return FALSE;
+ }
+
+ qt_glClearColor = (_glClearColor) gl.resolve("glClearColor");
+ qt_glClearIndex = (_glClearIndex) gl.resolve("glClearIndex");
+ qt_glColor3ub = (_glColor3ub) gl.resolve("glColor3ub");
+ qt_glDeleteLists = (_glDeleteLists) gl.resolve("glDeleteLists");
+ qt_glDrawBuffer = (_glDrawBuffer) gl.resolve("glDrawBuffer");
+ qt_glFlush = (_glFlush) gl.resolve("glFlush");
+ qt_glIndexi = (_glIndexi) gl.resolve("glIndexi");
+ qt_glListBase = (_glListBase) gl.resolve("glListBase");
+ qt_glLoadIdentity = (_glLoadIdentity) gl.resolve("glLoadIdentity");
+ qt_glMatrixMode = (_glMatrixMode) gl.resolve("glMatrixMode");
+ qt_glOrtho = (_glOrtho) gl.resolve("glOrtho");
+ qt_glPopAttrib = (_glPopAttrib) gl.resolve("glPopAttrib");
+ qt_glPopMatrix = (_glPopMatrix) gl.resolve("glPopMatrix");
+ qt_glPushAttrib = (_glPushAttrib) gl.resolve("glPushAttrib");
+ qt_glPushMatrix = (_glPushMatrix) gl.resolve("glPushMatrix");
+ qt_glRasterPos2i = (_glRasterPos2i) gl.resolve("glRasterPos2i");
+ qt_glRasterPos3d = (_glRasterPos3d) gl.resolve("glRasterPos3d");
+ qt_glReadPixels = (_glReadPixels) gl.resolve("glReadPixels");
+ qt_glViewport = (_glViewport) gl.resolve("glViewport");
+ qt_glPixelStorei = (_glPixelStorei) gl.resolve("glPixelStorei");
+ qt_glBitmap = (_glBitmap) gl.resolve("glBitmap");
+ qt_glDrawPixels = (_glDrawPixels) gl.resolve("glDrawPixels");
+ qt_glNewList = (_glNewList) gl.resolve("glNewList");
+ qt_glGetFloatv = (_glGetFloatv) gl.resolve("glGetFloatv");
+ qt_glGetIntegerv = (_glGetIntegerv) gl.resolve("glGetIntegerv");
+ qt_glEndList = (_glEndList) gl.resolve("glEndList");
+
+ qt_glXChooseVisual = (_glXChooseVisual) gl.resolve("glXChooseVisual");
+ qt_glXCreateContext = (_glXCreateContext) gl.resolve("glXCreateContext");
+ qt_glXCreateGLXPixmap = (_glXCreateGLXPixmap) gl.resolve("glXCreateGLXPixmap");
+ qt_glXDestroyContext = (_glXDestroyContext) gl.resolve("glXDestroyContext");
+ qt_glXDestroyGLXPixmap = (_glXDestroyGLXPixmap) gl.resolve("glXDestroyGLXPixmap");
+ qt_glXGetClientString = (_glXGetClientString) gl.resolve("glXGetClientString");
+ qt_glXGetConfig = (_glXGetConfig) gl.resolve("glXGetConfig");
+ qt_glXIsDirect = (_glXIsDirect) gl.resolve("glXIsDirect");
+ qt_glXMakeCurrent = (_glXMakeCurrent) gl.resolve("glXMakeCurrent");
+ qt_glXQueryExtension = (_glXQueryExtension) gl.resolve("glXQueryExtension");
+ qt_glXQueryExtensionsString = (_glXQueryExtensionsString) gl.resolve("glXQueryExtensionsString");
+ qt_glXQueryServerString = (_glXQueryServerString) gl.resolve("glXQueryServerString");
+ qt_glXSwapBuffers = (_glXSwapBuffers) gl.resolve("glXSwapBuffers");
+ qt_glXUseXFont = (_glXUseXFont) gl.resolve("glXUseXFont");
+ qt_glXWaitX = (_glXWaitX) gl.resolve("glXWaitX");
+ gl_syms_resolved = TRUE;
+ return TRUE;
+}
+#endif // QT_DLOPEN_OPENGL
+
+
+/*
+ The choose_cmap function is internal and used by 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<CMapEntry> *cmap_dict = 0;
+static bool mesa_gl = FALSE;
+static TQIntDict< TQMap<int, TQRgb> > *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<CMapEntry>;
+ const char *v = glXQueryServerString( dpy, vi->screen, GLX_VERSION );
+ if ( v )
+ mesa_gl = strstr(v,"Mesa") != 0;
+ qAddPostRoutine( cleanup_cmaps );
+ }
+
+ CMapEntry *x = cmap_dict->find( (long) vi->visualid + ( vi->screen * 256 ) );
+ if ( x ) // found colormap for visual
+ return x->cmap;
+
+ x = new CMapEntry();
+
+ XStandardColormap *c;
+ int n, i;
+
+ // qDebug( "Choosing cmap for vID %0x", vi->visualid );
+
+ if ( vi->visualid ==
+ XVisualIDFromVisual( (Visual*)TQPaintDevice::x11AppVisual( vi->screen ) ) ) {
+ // qDebug( "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];
+ //qDebug( "Using HP_RGB scmap" );
+
+ }
+ i++;
+ }
+ XFree( (char *)c );
+ }
+ }
+ }
+#if !defined(Q_OS_SOLARIS)
+ if ( !x->cmap ) {
+#ifdef QT_DLOPEN_OPENGL
+ typedef Status (*_XmuLookupStandardColormap)( Display *dpy, int screen, VisualID visualid, unsigned int depth,
+ Atom property, Bool replace, Bool retain );
+ _XmuLookupStandardColormap qt_XmuLookupStandardColormap;
+ qt_XmuLookupStandardColormap = (_XmuLookupStandardColormap) TQLibrary::resolve("Xmu.so.6", "XmuLookupStandardColormap");
+ if (!qt_XmuLookupStandardColormap)
+ qFatal("Unable to resolve Xmu symbols - please check your Xmu library installation.");
+#define XmuLookupStandardColormap qt_XmuLookupStandardColormap
+
+#endif
+
+ if ( XmuLookupStandardColormap(dpy,vi->screen,vi->visualid,vi->depth,
+ XA_RGB_DEFAULT_MAP,FALSE,TRUE) ) {
+ if ( XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
+ XA_RGB_DEFAULT_MAP) ) {
+ i = 0;
+ while ( i < n && x->cmap == 0 ) {
+ if ( c[i].visualid == vi->visualid ) {
+ x->cmap = c[i].colormap;
+ x->scmap = c[i];
+ //qDebug( "Using RGB_DEFAULT scmap" );
+ }
+ i++;
+ }
+ XFree( (char *)c );
+ }
+ }
+ }
+#endif
+ if ( !x->cmap ) { // no shared cmap found
+ x->cmap = XCreateColormap( dpy, RootWindow(dpy,vi->screen), vi->visual,
+ AllocNone );
+ x->alloc = TRUE;
+ // qDebug( "Allocating cmap" );
+ }
+
+ // associate cmap with visualid
+ cmap_dict->insert( (long) vi->visualid + ( vi->screen * 256 ), x );
+ return x->cmap;
+}
+
+struct TransColor
+{
+ VisualID vis;
+ int screen;
+ long color;
+};
+
+static TQMemArray<TransColor> trans_colors;
+static int trans_colors_init = FALSE;
+
+
+static void find_trans_colors()
+{
+ struct OverlayProp {
+ long visual;
+ long type;
+ long value;
+ long layer;
+ };
+
+ trans_colors_init = TRUE;
+
+ Display* appDisplay = 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(qt_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)
+ qWarning("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 = (Q_UINT32)glXCreateGLXPixmap( disp, (XVisualInfo *)vi,
+ d->paintDevice->handle() );
+#endif
+ if ( !gpm )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*!
+ <strong>X11 only</strong>: This virtual function tries to find a
+ visual that matches the format, reducing the demands if the original
+ request cannot be met.
+
+ The algorithm for reducing the demands of the format is tquite
+ simple-minded, so override this method in your subclass if your
+ application has spcific retquirements 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
+
+ <strong>X11 only</strong>: This virtual function chooses a visual
+ that matches the OpenGL \link format() format\endlink. Reimplement this
+ function in a subclass if you need a custom visual.
+
+ \sa chooseContext()
+*/
+
+void *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 ) {
+ // Retquired 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)
+ qWarning("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)
+ // qDebug("makeCurrent: %i, vi=%i, vi->vi=%i, vi->id=%i", (int)this, (int)vi, (int)((XVisualInfo*)vi)->visual, (int)((XVisualInfo*)vi)->visualid );
+ if ( !ok )
+ qWarning("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(qRgb(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<int, TQRgb> >;
+ }
+ TQMap<int, TQRgb> *cmap;
+ if ((cmap = qglcmap_dict->find((long) info->visualid)) == 0) {
+ cmap = new TQMap<int, TQRgb>;
+ qglcmap_dict->insert((long) info->visualid, cmap);
+ }
+
+ // already in the map?
+ TQRgb target = c.rgb();
+ TQMap<int, TQRgb>::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)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ col.blue = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5);
+ XStoreColor(TQPaintDevice::x11AppDisplay(), x->cmap, &col);
+
+ cmap->insert(color_map_entry, target);
+ return color_map_entry;
+ }
+ }
+ return 0;
+}
+
+#ifndef QT_NO_XFTFREETYPE
+/*! \internal
+ This is basically a substitute for glxUseXFont() which can only
+ handle XLFD fonts. This version relies on XFT v2 to render the
+ glyphs, but it works with all fonts that XFT2 provides - both
+ antialiased and aliased bitmap and outline fonts.
+*/
+void qgl_use_font(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) {
+ qDebug("failed loading glyph %d from font", i);
+ Q_ASSERT(!err);
+ }
+ err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal
+ : ft_render_mode_mono));
+ if (err) {
+ qDebug("failed rendering glyph %d from font", i);
+ Q_ASSERT(!err);
+ }
+
+ FT_Bitmap bm = face->glyph->bitmap;
+ x0 = face->glyph->metrics.horiBearingX >> 6;
+ y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6;
+ dx = face->glyph->metrics.horiAdvance >> 6;
+ dy = 0;
+ int sz = bm.pitch * bm.rows;
+ uint *aa_glyph = 0;
+ uchar *ua_glyph = 0;
+
+ if (antialiased)
+ aa_glyph = new uint[sz];
+ else
+ ua_glyph = new uchar[sz];
+
+ // convert to GL format
+ for (int y = 0; y < bm.rows; ++y) {
+ for (int x = 0; x < bm.pitch; ++x) {
+ int c1 = y*bm.pitch + x;
+ int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x;
+ if (antialiased) {
+ aa_glyph[c1] = (int(color[0]*255) << 24)
+ | (int(color[1]*255) << 16)
+ | (int(color[2]*255) << 8) | bm.buffer[c2];
+ } else {
+ ua_glyph[c1] = bm.buffer[c2];
+ }
+ }
+ }
+
+ glNewList(list, GL_COMPILE);
+ if (antialiased) {
+ // calling glBitmap() is just a trick to move the current
+ // raster pos, since glGet*() won't work in display lists
+ glBitmap(0, 0, 0, 0, x0, -y0, 0);
+ glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph);
+ glBitmap(0, 0, 0, 0, dx-x0, y0, 0);
+ } else {
+ glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph);
+ }
+ glEndList();
+ antialiased ? delete[] aa_glyph : delete[] ua_glyph;
+ }
+
+#ifdef QT_XFT2
+ XftUnlockFace(engine->font());
+#endif
+
+ // restore pixel unpack settings
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment);
+}
+#endif
+
+void TQGLContext::generateFontDisplayLists( const TQFont & fnt, int listBase )
+{
+ TQFont f(fnt);
+ TQFontEngine *engine = f.d->engineForScript(TQFont::Latin);
+
+#ifndef QT_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
+{
+ Q_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(Q_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
+ qWarning( "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)
+ qWarning( "TQGLWidget::setContext: Cannot set null context" );
+#endif
+ return;
+ }
+ if ( !context->deviceIsPixmap() && context->device() != this ) {
+#if defined(QT_CHECK_STATE)
+ qWarning( "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; i++ ) {
+ if ( cmw[i] == winId() ) { // replace old window
+ cmw[i] = w;
+ break;
+ }
+ }
+ if ( i >= count ) // append new window
+ cmw[count++] = w;
+ } else {
+ count = 1;
+ cmw = new Window[count];
+ cmw[0] = w;
+ }
+
+#if defined(GLX_MESA_release_buffers) && defined(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 = (Q_UINT32)glXCreateGLXPixmap( x11Display(),
+ (XVisualInfo*)glcx->vi,
+ (Pixmap)pm->handle() );
+#endif
+
+ if ( !glXMakeCurrent( x11Display(), glPm, (GLXContext)glcx->cx ) ) {
+ glXDestroyGLXPixmap( x11Display(), glPm );
+ return FALSE;
+ }
+
+ glDrawBuffer( GL_FRONT );
+ if ( !glcx->initialized() )
+ glInit();
+ resizeGL( pm->width(), pm->height() );
+ paintGL();
+ glFlush();
+ makeCurrent();
+ glXDestroyGLXPixmap( x11Display(), glPm );
+ resizeGL( width(), height() );
+ return TRUE;
+}
+
+const 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)( (qRed( color ) / 255.0) * 65535.0 + 0.5 );
+ c.green = (ushort)( (qGreen( color ) / 255.0) * 65535.0 + 0.5 );
+ c.blue = (ushort)( (qBlue( color ) / 255.0) * 65535.0 + 0.5 );
+ c.flags = DoRed | DoGreen | DoBlue;
+ XStoreColor( tlw->x11Display(), cmap, &c );
+ }
+}
+
+/*\internal
+ Check whether the given visual supports dynamic colormaps or not.
+*/
+static bool qCanAllocColors( 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 ) ) {
+ qWarning( "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