diff options
Diffstat (limited to 'src/opengl/qgl_x11.cpp')
-rw-r--r-- | src/opengl/qgl_x11.cpp | 1406 |
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 |