src/opengl/qgl_x11.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qgl.h"
       
    43 #include "qgl_p.h"
       
    44 
       
    45 #include "qmap.h"
       
    46 #include "qapplication.h"
       
    47 #include "qcolormap.h"
       
    48 #include "qdesktopwidget.h"
       
    49 #include "qpixmap.h"
       
    50 #include "qhash.h"
       
    51 #include "qlibrary.h"
       
    52 #include "qdebug.h"
       
    53 #include <private/qfontengine_ft_p.h>
       
    54 #include <private/qt_x11_p.h>
       
    55 #include <private/qpixmap_x11_p.h>
       
    56 #ifdef Q_OS_HPUX
       
    57 // for GLXPBuffer
       
    58 #include <private/qglpixelbuffer_p.h>
       
    59 #endif
       
    60 
       
    61 // We always define GLX_EXT_texture_from_pixmap ourselves because
       
    62 // we can't trust system headers to do it properly
       
    63 #define GLX_EXT_texture_from_pixmap 1
       
    64 
       
    65 #define INT8  dummy_INT8
       
    66 #define INT32 dummy_INT32
       
    67 #include <GL/glx.h>
       
    68 #undef  INT8
       
    69 #undef  INT32
       
    70 
       
    71 #include <X11/Xlib.h>
       
    72 #include <X11/Xutil.h>
       
    73 #include <X11/Xos.h>
       
    74 #ifdef Q_OS_VXWORS
       
    75 #  ifdef open
       
    76 #    undef open
       
    77 #  endif
       
    78 #  ifdef getpid
       
    79 #    undef getpid
       
    80 #  endif
       
    81 #endif // Q_OS_VXWORKS
       
    82 #include <X11/Xatom.h>
       
    83 
       
    84 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
       
    85 #include <dlfcn.h>
       
    86 #endif
       
    87 
       
    88 QT_BEGIN_NAMESPACE
       
    89 
       
    90 extern Drawable qt_x11Handle(const QPaintDevice *pd);
       
    91 extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
       
    92 
       
    93 #ifndef GLX_ARB_multisample
       
    94 #define GLX_SAMPLE_BUFFERS_ARB  100000
       
    95 #define GLX_SAMPLES_ARB         100001
       
    96 #endif
       
    97 
       
    98 #ifndef GLX_TEXTURE_2D_BIT_EXT
       
    99 #define GLX_TEXTURE_2D_BIT_EXT             0x00000002
       
   100 #define GLX_TEXTURE_RECTANGLE_BIT_EXT      0x00000004
       
   101 #define GLX_BIND_TO_TEXTURE_RGB_EXT        0x20D0
       
   102 #define GLX_BIND_TO_TEXTURE_RGBA_EXT       0x20D1
       
   103 #define GLX_BIND_TO_MIPMAP_TEXTURE_EXT     0x20D2
       
   104 #define GLX_BIND_TO_TEXTURE_TARGETS_EXT    0x20D3
       
   105 #define GLX_Y_INVERTED_EXT                 0x20D4
       
   106 #define GLX_TEXTURE_FORMAT_EXT             0x20D5
       
   107 #define GLX_TEXTURE_TARGET_EXT             0x20D6
       
   108 #define GLX_MIPMAP_TEXTURE_EXT             0x20D7
       
   109 #define GLX_TEXTURE_FORMAT_NONE_EXT        0x20D8
       
   110 #define GLX_TEXTURE_FORMAT_RGB_EXT         0x20D9
       
   111 #define GLX_TEXTURE_FORMAT_RGBA_EXT        0x20DA
       
   112 #define GLX_TEXTURE_2D_EXT                 0x20DC
       
   113 #define GLX_TEXTURE_RECTANGLE_EXT          0x20DD
       
   114 #define GLX_FRONT_LEFT_EXT                 0x20DE
       
   115 #endif
       
   116 
       
   117 /*
       
   118   The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext()
       
   119   and GLX (not Windows).  If the application can't find any sharable
       
   120   colormaps, it must at least create as few colormaps as possible.  The
       
   121   dictionary solution below ensures only one colormap is created per visual.
       
   122   Colormaps are also deleted when the application terminates.
       
   123 */
       
   124 
       
   125 struct QCMapEntry {
       
   126     QCMapEntry();
       
   127     ~QCMapEntry();
       
   128 
       
   129     Colormap cmap;
       
   130     bool alloc;
       
   131     XStandardColormap scmap;
       
   132 };
       
   133 
       
   134 QCMapEntry::QCMapEntry()
       
   135 {
       
   136     cmap = 0;
       
   137     alloc = false;
       
   138     scmap.colormap = 0;
       
   139 }
       
   140 
       
   141 QCMapEntry::~QCMapEntry()
       
   142 {
       
   143     if (alloc)
       
   144         XFreeColormap(X11->display, cmap);
       
   145 }
       
   146 typedef QHash<int, QCMapEntry *> CMapEntryHash;
       
   147 typedef QHash<int, QMap<int, QRgb> > GLCMapHash;
       
   148 static bool mesa_gl = false;
       
   149 static bool first_time = true;
       
   150 
       
   151 static void cleanup_cmaps();
       
   152 
       
   153 struct QGLCMapCleanupHandler {
       
   154     QGLCMapCleanupHandler() {
       
   155         cmap_hash = new CMapEntryHash;
       
   156         qglcmap_hash = new GLCMapHash;
       
   157     }
       
   158     ~QGLCMapCleanupHandler() {
       
   159         delete cmap_hash;
       
   160         delete qglcmap_hash;
       
   161     }
       
   162     CMapEntryHash *cmap_hash;
       
   163     GLCMapHash *qglcmap_hash;
       
   164 };
       
   165 Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler)
       
   166 
       
   167 static void cleanup_cmaps()
       
   168 {
       
   169     CMapEntryHash *hash = cmap_handler()->cmap_hash;
       
   170     QHash<int, QCMapEntry *>::ConstIterator it = hash->constBegin();
       
   171     while (it != hash->constEnd()) {
       
   172         delete it.value();
       
   173         ++it;
       
   174     }
       
   175 
       
   176     hash->clear();
       
   177     cmap_handler()->qglcmap_hash->clear();
       
   178 }
       
   179 
       
   180 Colormap qt_gl_choose_cmap(Display *dpy, XVisualInfo *vi)
       
   181 {
       
   182     if (first_time) {
       
   183         const char *v = glXQueryServerString(dpy, vi->screen, GLX_VERSION);
       
   184         if (v)
       
   185             mesa_gl = (strstr(v, "Mesa") != 0);
       
   186         first_time = false;
       
   187     }
       
   188 
       
   189     CMapEntryHash *hash = cmap_handler()->cmap_hash;
       
   190     CMapEntryHash::ConstIterator it = hash->constFind((long) vi->visualid + (vi->screen * 256));
       
   191     if (it != hash->constEnd())
       
   192         return it.value()->cmap; // found colormap for visual
       
   193 
       
   194     if (vi->visualid ==
       
   195         XVisualIDFromVisual((Visual *) QX11Info::appVisual(vi->screen))) {
       
   196         // qDebug("Using x11AppColormap");
       
   197         return QX11Info::appColormap(vi->screen);
       
   198     }
       
   199 
       
   200     QCMapEntry *x = new QCMapEntry();
       
   201 
       
   202     XStandardColormap *c;
       
   203     int n, i;
       
   204 
       
   205     // qDebug("Choosing cmap for vID %0x", vi->visualid);
       
   206 
       
   207     if (mesa_gl) {                                // we're using MesaGL
       
   208         Atom hp_cmaps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", true);
       
   209         if (hp_cmaps && vi->visual->c_class == TrueColor && vi->depth == 8) {
       
   210             if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
       
   211                                  hp_cmaps)) {
       
   212                 i = 0;
       
   213                 while (i < n && x->cmap == 0) {
       
   214                     if (c[i].visualid == vi->visual->visualid) {
       
   215                         x->cmap = c[i].colormap;
       
   216                         x->scmap = c[i];
       
   217                         //qDebug("Using HP_RGB scmap");
       
   218 
       
   219                     }
       
   220                     i++;
       
   221                 }
       
   222                 XFree((char *)c);
       
   223             }
       
   224         }
       
   225     }
       
   226     if (!x->cmap) {
       
   227         if (XGetRGBColormaps(dpy,RootWindow(dpy,vi->screen),&c,&n,
       
   228                              XA_RGB_DEFAULT_MAP)) {
       
   229             for (int i = 0; i < n && x->cmap == 0; ++i) {
       
   230                 if (!c[i].red_max ||
       
   231                     !c[i].green_max ||
       
   232                     !c[i].blue_max ||
       
   233                     !c[i].red_mult ||
       
   234                     !c[i].green_mult ||
       
   235                     !c[i].blue_mult)
       
   236                     continue; // invalid stdcmap
       
   237                 if (c[i].visualid == vi->visualid) {
       
   238                     x->cmap = c[i].colormap;
       
   239                     x->scmap = c[i];
       
   240                     //qDebug("Using RGB_DEFAULT scmap");
       
   241                 }
       
   242             }
       
   243             XFree((char *)c);
       
   244         }
       
   245     }
       
   246     if (!x->cmap) {                                // no shared cmap found
       
   247         x->cmap = XCreateColormap(dpy, RootWindow(dpy,vi->screen), vi->visual,
       
   248                                   AllocNone);
       
   249         x->alloc = true;
       
   250         // qDebug("Allocating cmap");
       
   251     }
       
   252 
       
   253     // colormap hash should be cleanup only when the QApplication dtor is called
       
   254     if (hash->isEmpty())
       
   255         qAddPostRoutine(cleanup_cmaps);
       
   256 
       
   257     // associate cmap with visualid
       
   258     hash->insert((long) vi->visualid + (vi->screen * 256), x);
       
   259     return x->cmap;
       
   260 }
       
   261 
       
   262 struct QTransColor
       
   263 {
       
   264     VisualID vis;
       
   265     int screen;
       
   266     long color;
       
   267 };
       
   268 
       
   269 static QVector<QTransColor> trans_colors;
       
   270 static int trans_colors_init = false;
       
   271 
       
   272 static void find_trans_colors()
       
   273 {
       
   274     struct OverlayProp {
       
   275         long  visual;
       
   276         long  type;
       
   277         long  value;
       
   278         long  layer;
       
   279     };
       
   280 
       
   281     trans_colors_init = true;
       
   282 
       
   283     Display* appDisplay = X11->display;
       
   284 
       
   285     int scr;
       
   286     int lastsize = 0;
       
   287     for (scr = 0; scr < ScreenCount(appDisplay); scr++) {
       
   288         QWidget* rootWin = QApplication::desktop()->screen(scr);
       
   289         if (!rootWin)
       
   290             return;                                        // Should not happen
       
   291         Atom overlayVisualsAtom = XInternAtom(appDisplay,
       
   292                                                "SERVER_OVERLAY_VISUALS", True);
       
   293         if (overlayVisualsAtom == XNone)
       
   294             return;                                        // Server has no overlays
       
   295 
       
   296         Atom actualType;
       
   297         int actualFormat;
       
   298         ulong nItems;
       
   299         ulong bytesAfter;
       
   300         unsigned char *retval = 0;
       
   301         int res = XGetWindowProperty(appDisplay, rootWin->winId(),
       
   302                                       overlayVisualsAtom, 0, 10000, False,
       
   303                                       overlayVisualsAtom, &actualType,
       
   304                                       &actualFormat, &nItems, &bytesAfter,
       
   305                                       &retval);
       
   306 
       
   307         if (res != Success || actualType != overlayVisualsAtom
       
   308              || actualFormat != 32 || nItems < 4 || !retval)
       
   309             return;                                        // Error reading property
       
   310 
       
   311         OverlayProp *overlayProps = (OverlayProp *)retval;
       
   312 
       
   313         int numProps = nItems / 4;
       
   314         trans_colors.resize(lastsize + numProps);
       
   315         int j = lastsize;
       
   316         for (int i = 0; i < numProps; i++) {
       
   317             if (overlayProps[i].type == 1) {
       
   318                 trans_colors[j].vis = (VisualID)overlayProps[i].visual;
       
   319                 trans_colors[j].screen = scr;
       
   320                 trans_colors[j].color = (int)overlayProps[i].value;
       
   321                 j++;
       
   322             }
       
   323         }
       
   324         XFree(overlayProps);
       
   325         lastsize = j;
       
   326         trans_colors.resize(lastsize);
       
   327     }
       
   328 }
       
   329 
       
   330 /*****************************************************************************
       
   331   QGLFormat UNIX/GLX-specific code
       
   332  *****************************************************************************/
       
   333 
       
   334 void* qglx_getProcAddress(const char* procName)
       
   335 {
       
   336     // On systems where the GL driver is pluggable (like Mesa), we have to use
       
   337     // the glXGetProcAddressARB extension to resolve other function pointers as
       
   338     // the symbols wont be in the GL library, but rather in a plugin loaded by
       
   339     // the GL library.
       
   340     typedef void* (*qt_glXGetProcAddressARB)(const char *);
       
   341     static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
       
   342     static bool triedResolvingGlxGetProcAddress = false;
       
   343     if (!triedResolvingGlxGetProcAddress) {
       
   344         triedResolvingGlxGetProcAddress = true;
       
   345         QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
       
   346         if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
       
   347 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
       
   348             void *handle = dlopen(NULL, RTLD_LAZY);
       
   349             if (handle) {
       
   350                 glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
       
   351                 dlclose(handle);
       
   352             }
       
   353             if (!glXGetProcAddressARB)
       
   354 #endif
       
   355             {
       
   356 #if !defined(QT_NO_LIBRARY)
       
   357                 extern const QString qt_gl_library_name();
       
   358                 QLibrary lib(qt_gl_library_name());
       
   359                 glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
       
   360 #endif
       
   361             }
       
   362         }
       
   363     }
       
   364 
       
   365     void *procAddress = 0;
       
   366     if (glXGetProcAddressARB)
       
   367         procAddress = glXGetProcAddressARB(procName);
       
   368 
       
   369     // If glXGetProcAddress didn't work, try looking the symbol up in the GL library
       
   370 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
       
   371     if (!procAddress) {
       
   372         void *handle = dlopen(NULL, RTLD_LAZY);
       
   373         if (handle) {
       
   374             procAddress = dlsym(handle, procName);
       
   375             dlclose(handle);
       
   376         }
       
   377     }
       
   378 #endif
       
   379 #if !defined(QT_NO_LIBRARY)
       
   380     if (!procAddress) {
       
   381         extern const QString qt_gl_library_name();
       
   382         QLibrary lib(qt_gl_library_name());
       
   383         procAddress = lib.resolve(procName);
       
   384     }
       
   385 #endif
       
   386 
       
   387     return procAddress;
       
   388 }
       
   389 
       
   390 bool QGLFormat::hasOpenGL()
       
   391 {
       
   392     return glXQueryExtension(X11->display, 0, 0) != 0;
       
   393 }
       
   394 
       
   395 
       
   396 bool QGLFormat::hasOpenGLOverlays()
       
   397 {
       
   398     if (!trans_colors_init)
       
   399         find_trans_colors();
       
   400     return trans_colors.size() > 0;
       
   401 }
       
   402 
       
   403 /*****************************************************************************
       
   404   QGLContext UNIX/GLX-specific code
       
   405  *****************************************************************************/
       
   406 
       
   407 bool QGLContext::chooseContext(const QGLContext* shareContext)
       
   408 {
       
   409     Q_D(QGLContext);
       
   410     const QX11Info *xinfo = qt_x11Info(d->paintDevice);
       
   411 
       
   412     Display* disp = xinfo->display();
       
   413     d->vi = chooseVisual();
       
   414     if (!d->vi)
       
   415         return false;
       
   416 
       
   417     if (deviceIsPixmap() &&
       
   418          (((XVisualInfo*)d->vi)->depth != xinfo->depth() ||
       
   419           ((XVisualInfo*)d->vi)->screen != xinfo->screen()))
       
   420     {
       
   421         XFree(d->vi);
       
   422         XVisualInfo appVisInfo;
       
   423         memset(&appVisInfo, 0, sizeof(XVisualInfo));
       
   424         appVisInfo.visualid = XVisualIDFromVisual((Visual *) xinfo->visual());
       
   425         appVisInfo.screen = xinfo->screen();
       
   426         int nvis;
       
   427         d->vi = XGetVisualInfo(disp, VisualIDMask | VisualScreenMask, &appVisInfo, &nvis);
       
   428         if (!d->vi)
       
   429             return false;
       
   430 
       
   431         int useGL;
       
   432         glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_USE_GL, &useGL);
       
   433         if (!useGL)
       
   434             return false;        //# Chickening out already...
       
   435     }
       
   436     int res;
       
   437     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_LEVEL, &res);
       
   438     d->glFormat.setPlane(res);
       
   439     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DOUBLEBUFFER, &res);
       
   440     d->glFormat.setDoubleBuffer(res);
       
   441     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_DEPTH_SIZE, &res);
       
   442     d->glFormat.setDepth(res);
       
   443     if (d->glFormat.depth())
       
   444         d->glFormat.setDepthBufferSize(res);
       
   445     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RGBA, &res);
       
   446     d->glFormat.setRgba(res);
       
   447     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_RED_SIZE, &res);
       
   448     d->glFormat.setRedBufferSize(res);
       
   449     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_GREEN_SIZE, &res);
       
   450     d->glFormat.setGreenBufferSize(res);
       
   451     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_BLUE_SIZE, &res);
       
   452     d->glFormat.setBlueBufferSize(res);
       
   453     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ALPHA_SIZE, &res);
       
   454     d->glFormat.setAlpha(res);
       
   455     if (d->glFormat.alpha())
       
   456         d->glFormat.setAlphaBufferSize(res);
       
   457     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_ACCUM_RED_SIZE, &res);
       
   458     d->glFormat.setAccum(res);
       
   459     if (d->glFormat.accum())
       
   460         d->glFormat.setAccumBufferSize(res);
       
   461     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STENCIL_SIZE, &res);
       
   462     d->glFormat.setStencil(res);
       
   463     if (d->glFormat.stencil())
       
   464         d->glFormat.setStencilBufferSize(res);
       
   465     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_STEREO, &res);
       
   466     d->glFormat.setStereo(res);
       
   467     glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLE_BUFFERS_ARB, &res);
       
   468     d->glFormat.setSampleBuffers(res);
       
   469     if (d->glFormat.sampleBuffers()) {
       
   470         glXGetConfig(disp, (XVisualInfo*)d->vi, GLX_SAMPLES_ARB, &res);
       
   471         d->glFormat.setSamples(res);
       
   472     }
       
   473 
       
   474     Bool direct = format().directRendering() ? True : False;
       
   475 
       
   476     if (shareContext &&
       
   477          (!shareContext->isValid() || !shareContext->d_func()->cx)) {
       
   478             qWarning("QGLContext::chooseContext(): Cannot share with invalid context");
       
   479             shareContext = 0;
       
   480     }
       
   481 
       
   482     // 1. Sharing between rgba and color-index will give wrong colors.
       
   483     // 2. Contexts cannot be shared btw. direct/non-direct renderers.
       
   484     // 3. Pixmaps cannot share contexts that are set up for direct rendering.
       
   485     // 4. If the contexts are not created on the same screen, they can't be shared
       
   486 
       
   487     if (shareContext
       
   488         && (format().rgba() != shareContext->format().rgba()
       
   489             || (deviceIsPixmap() && glXIsDirect(disp, (GLXContext)shareContext->d_func()->cx))
       
   490             || (shareContext->d_func()->screen != xinfo->screen())))
       
   491     {
       
   492         shareContext = 0;
       
   493     }
       
   494 
       
   495     d->cx = 0;
       
   496     if (shareContext) {
       
   497         d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi,
       
   498                                (GLXContext)shareContext->d_func()->cx, direct);
       
   499         d->screen = ((XVisualInfo*)d->vi)->screen;
       
   500         if (d->cx) {
       
   501             QGLContext *share = const_cast<QGLContext *>(shareContext);
       
   502             d->sharing = true;
       
   503             share->d_func()->sharing = true;
       
   504         }
       
   505     }
       
   506     if (!d->cx) {
       
   507         d->cx = glXCreateContext(disp, (XVisualInfo *)d->vi, NULL, direct);
       
   508         d->screen = ((XVisualInfo*)d->vi)->screen;
       
   509     }
       
   510     if (!d->cx)
       
   511         return false;
       
   512     d->glFormat.setDirectRendering(glXIsDirect(disp, (GLXContext)d->cx));
       
   513     if (deviceIsPixmap()) {
       
   514 #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT)
       
   515         d->gpm = glXCreateGLXPixmapMESA(disp, (XVisualInfo *)d->vi,
       
   516                                         qt_x11Handle(d->paintDevice),
       
   517                                         qt_gl_choose_cmap(disp, (XVisualInfo *)d->vi));
       
   518 #else
       
   519         d->gpm = (quint32)glXCreateGLXPixmap(disp, (XVisualInfo *)d->vi,
       
   520                                               qt_x11Handle(d->paintDevice));
       
   521 #endif
       
   522         if (!d->gpm)
       
   523             return false;
       
   524     }
       
   525     QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
       
   526     if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
       
   527         if (d->glFormat.swapInterval() == -1)
       
   528             d->glFormat.setSwapInterval(0);
       
   529     } else {
       
   530         d->glFormat.setSwapInterval(-1);
       
   531     }
       
   532     return true;
       
   533 }
       
   534 
       
   535 /*
       
   536   See qgl.cpp for qdoc comment.
       
   537  */
       
   538 void *QGLContext::chooseVisual()
       
   539 {
       
   540     Q_D(QGLContext);
       
   541     static const int bufDepths[] = { 8, 4, 2, 1 };        // Try 16, 12 also?
       
   542     //todo: if pixmap, also make sure that vi->depth == pixmap->depth
       
   543     void* vis = 0;
       
   544     int i = 0;
       
   545     bool fail = false;
       
   546     QGLFormat fmt = format();
       
   547     bool tryDouble = !fmt.doubleBuffer();  // Some GL impl's only have double
       
   548     bool triedDouble = false;
       
   549     bool triedSample = false;
       
   550     if (fmt.sampleBuffers())
       
   551         fmt.setSampleBuffers(QGLExtensions::glExtensions & QGLExtensions::SampleBuffers);
       
   552     while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) {
       
   553         if (!fmt.rgba() && bufDepths[i] > 1) {
       
   554             i++;
       
   555             continue;
       
   556         }
       
   557         if (tryDouble) {
       
   558             fmt.setDoubleBuffer(true);
       
   559             tryDouble = false;
       
   560             triedDouble = true;
       
   561             continue;
       
   562         } else if (triedDouble) {
       
   563             fmt.setDoubleBuffer(false);
       
   564             triedDouble = false;
       
   565         }
       
   566         if (!triedSample && fmt.sampleBuffers()) {
       
   567             fmt.setSampleBuffers(false);
       
   568             triedSample = true;
       
   569             continue;
       
   570         }
       
   571         if (fmt.stereo()) {
       
   572             fmt.setStereo(false);
       
   573             continue;
       
   574         }
       
   575         if (fmt.accum()) {
       
   576             fmt.setAccum(false);
       
   577             continue;
       
   578         }
       
   579         if (fmt.stencil()) {
       
   580             fmt.setStencil(false);
       
   581             continue;
       
   582         }
       
   583         if (fmt.alpha()) {
       
   584             fmt.setAlpha(false);
       
   585             continue;
       
   586         }
       
   587         if (fmt.depth()) {
       
   588             fmt.setDepth(false);
       
   589             continue;
       
   590         }
       
   591         if (fmt.doubleBuffer()) {
       
   592             fmt.setDoubleBuffer(false);
       
   593             continue;
       
   594         }
       
   595         fail = true;
       
   596     }
       
   597     d->glFormat = fmt;
       
   598     return vis;
       
   599 }
       
   600 
       
   601 /*
       
   602   See qgl.cpp for qdoc comment.
       
   603  */
       
   604 void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
       
   605 {
       
   606     Q_D(QGLContext);
       
   607     int spec[45];
       
   608     int i = 0;
       
   609     spec[i++] = GLX_LEVEL;
       
   610     spec[i++] = f.plane();
       
   611     const QX11Info *xinfo = qt_x11Info(d->paintDevice);
       
   612     bool useFBConfig = false;
       
   613 
       
   614 #if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER) && !defined(Q_OS_HPUX)
       
   615     /*
       
   616       HPUX defines GLX_VERSION_1_3 but does not implement the corresponding functions.
       
   617       Specifically glXChooseFBConfig and glXGetVisualFromFBConfig are not implemented.
       
   618      */
       
   619     QWidget* widget = 0;
       
   620     if (d->paintDevice->devType() == QInternal::Widget)
       
   621         widget = static_cast<QWidget*>(d->paintDevice);
       
   622 
       
   623     // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
       
   624     if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
       
   625         useFBConfig = true;
       
   626 #endif
       
   627 
       
   628 #if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
       
   629     static bool useTranspExt = false;
       
   630     static bool useTranspExtChecked = false;
       
   631     if (f.plane() && !useTranspExtChecked && d->paintDevice) {
       
   632         QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen()));
       
   633         useTranspExt = estr.contains("GLX_EXT_visual_info");
       
   634         //# (A bit simplistic; that could theoretically be a substring)
       
   635         if (useTranspExt) {
       
   636             QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR));
       
   637             useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround
       
   638             if (useTranspExt) {
       
   639                 // bug workaround - some systems (eg. FireGL) refuses to return an overlay
       
   640                 // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if
       
   641                 // the implementation supports transparent overlays
       
   642                 int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT,
       
   643                                   f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT,
       
   644                                   XNone };
       
   645                 XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec);
       
   646                 if (!vinf) {
       
   647                     useTranspExt = false;
       
   648                 }
       
   649             }
       
   650         }
       
   651 
       
   652         useTranspExtChecked = true;
       
   653     }
       
   654     if (f.plane() && useTranspExt && !useFBConfig) {
       
   655         // Required to avoid non-transparent overlay visual(!) on some systems
       
   656         spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
       
   657         spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
       
   658     }
       
   659 #endif
       
   660 
       
   661 #if defined(GLX_VERSION_1_3)  && !defined(Q_OS_HPUX)
       
   662     // GLX_RENDER_TYPE is only in glx >=1.3
       
   663     if (useFBConfig) {
       
   664         spec[i++] = GLX_RENDER_TYPE;
       
   665         spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
       
   666     }
       
   667 #endif
       
   668 
       
   669     if (f.doubleBuffer())
       
   670         spec[i++] = GLX_DOUBLEBUFFER;
       
   671         if (useFBConfig)
       
   672             spec[i++] = True;
       
   673     if (f.depth()) {
       
   674         spec[i++] = GLX_DEPTH_SIZE;
       
   675         spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
       
   676     }
       
   677     if (f.stereo()) {
       
   678         spec[i++] = GLX_STEREO;
       
   679         if (useFBConfig)
       
   680             spec[i++] = True;
       
   681     }
       
   682     if (f.stencil()) {
       
   683         spec[i++] = GLX_STENCIL_SIZE;
       
   684         spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
       
   685     }
       
   686     if (f.rgba()) {
       
   687         if (!useFBConfig)
       
   688             spec[i++] = GLX_RGBA;
       
   689         spec[i++] = GLX_RED_SIZE;
       
   690         spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
       
   691         spec[i++] = GLX_GREEN_SIZE;
       
   692         spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
       
   693         spec[i++] = GLX_BLUE_SIZE;
       
   694         spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
       
   695         if (f.alpha()) {
       
   696             spec[i++] = GLX_ALPHA_SIZE;
       
   697             spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
       
   698         }
       
   699         if (f.accum()) {
       
   700             spec[i++] = GLX_ACCUM_RED_SIZE;
       
   701             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
       
   702             spec[i++] = GLX_ACCUM_GREEN_SIZE;
       
   703             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
       
   704             spec[i++] = GLX_ACCUM_BLUE_SIZE;
       
   705             spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
       
   706             if (f.alpha()) {
       
   707                 spec[i++] = GLX_ACCUM_ALPHA_SIZE;
       
   708                 spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
       
   709             }
       
   710         }
       
   711     } else {
       
   712         spec[i++] = GLX_BUFFER_SIZE;
       
   713         spec[i++] = bufDepth;
       
   714     }
       
   715 
       
   716     if (f.sampleBuffers()) {
       
   717         spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
       
   718         spec[i++] = 1;
       
   719         spec[i++] = GLX_SAMPLES_ARB;
       
   720         spec[i++] = f.samples() == -1 ? 4 : f.samples();
       
   721     }
       
   722 
       
   723 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
   724     if (useFBConfig) {
       
   725         spec[i++] = GLX_DRAWABLE_TYPE;
       
   726         switch(d->paintDevice->devType()) {
       
   727         case QInternal::Pixmap:
       
   728             spec[i++] = GLX_PIXMAP_BIT;
       
   729             break;
       
   730         case QInternal::Pbuffer:
       
   731             spec[i++] = GLX_PBUFFER_BIT;
       
   732             break;
       
   733         default:
       
   734             qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType());
       
   735             // Fall-through & assume it's a window
       
   736         case QInternal::Widget:
       
   737             spec[i++] = GLX_WINDOW_BIT;
       
   738             break;
       
   739         };
       
   740     }
       
   741 #endif
       
   742 
       
   743     spec[i] = XNone;
       
   744 
       
   745 
       
   746     XVisualInfo* chosenVisualInfo = 0;
       
   747 
       
   748 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
   749     while (useFBConfig) {
       
   750         GLXFBConfig *configs;
       
   751         int configCount = 0;
       
   752         configs = glXChooseFBConfig(xinfo->display(), xinfo->screen(), spec, &configCount);
       
   753 
       
   754         if (!configs)
       
   755             break; // fallback to trying glXChooseVisual
       
   756 
       
   757         for (i = 0; i < configCount; ++i) {
       
   758             XVisualInfo* vi;
       
   759             vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]);
       
   760             if (!vi)
       
   761                 continue;
       
   762 
       
   763 #if !defined(QT_NO_XRENDER)
       
   764             QWidget* w = 0;
       
   765             if (d->paintDevice->devType() == QInternal::Widget)
       
   766                 w = static_cast<QWidget*>(d->paintDevice);
       
   767 
       
   768             if (w && w->testAttribute(Qt::WA_TranslucentBackground) && f.alpha()) {
       
   769                 // Attempt to find a config who's visual has a proper alpha channel
       
   770                 XRenderPictFormat *pictFormat;
       
   771                 pictFormat = XRenderFindVisualFormat(xinfo->display(), vi->visual);
       
   772 
       
   773                 if (pictFormat && (pictFormat->type == PictTypeDirect) && pictFormat->direct.alphaMask) {
       
   774                     // The pict format for the visual matching the FBConfig indicates ARGB
       
   775                     if (chosenVisualInfo)
       
   776                         XFree(chosenVisualInfo);
       
   777                     chosenVisualInfo = vi;
       
   778                     break;
       
   779                 }
       
   780             } else
       
   781 #endif //QT_NO_XRENDER
       
   782             if (chosenVisualInfo) {
       
   783                 // If we've got a visual we can use and we're not trying to find one with a
       
   784                 // real alpha channel, we might as well just use the one we've got
       
   785                 break;
       
   786             }
       
   787 
       
   788             if (!chosenVisualInfo)
       
   789                 chosenVisualInfo = vi; // Have something to fall back to
       
   790             else
       
   791                 XFree(vi);
       
   792         }
       
   793 
       
   794         XFree(configs);
       
   795         break;
       
   796     }
       
   797 #endif // defined(GLX_VERSION_1_3)
       
   798 
       
   799     if (!chosenVisualInfo)
       
   800         chosenVisualInfo = glXChooseVisual(xinfo->display(), xinfo->screen(), spec);
       
   801 
       
   802     return chosenVisualInfo;
       
   803 }
       
   804 
       
   805 
       
   806 void QGLContext::reset()
       
   807 {
       
   808     Q_D(QGLContext);
       
   809     if (!d->valid)
       
   810         return;
       
   811     d->cleanup();
       
   812     const QX11Info *xinfo = qt_x11Info(d->paintDevice);
       
   813     doneCurrent();
       
   814     if (d->gpm)
       
   815         glXDestroyGLXPixmap(xinfo->display(), (GLXPixmap)d->gpm);
       
   816     d->gpm = 0;
       
   817     glXDestroyContext(xinfo->display(), (GLXContext)d->cx);
       
   818     if (d->vi)
       
   819         XFree(d->vi);
       
   820     d->vi = 0;
       
   821     d->cx = 0;
       
   822     d->crWin = false;
       
   823     d->sharing = false;
       
   824     d->valid = false;
       
   825     d->transpColor = QColor();
       
   826     d->initDone = false;
       
   827     qgl_share_reg()->removeShare(this);
       
   828 }
       
   829 
       
   830 
       
   831 void QGLContext::makeCurrent()
       
   832 {
       
   833     Q_D(QGLContext);
       
   834     if (!d->valid) {
       
   835         qWarning("QGLContext::makeCurrent(): Cannot make invalid context current.");
       
   836         return;
       
   837     }
       
   838     const QX11Info *xinfo = qt_x11Info(d->paintDevice);
       
   839     bool ok = true;
       
   840     if (d->paintDevice->devType() == QInternal::Pixmap) {
       
   841         ok = glXMakeCurrent(xinfo->display(), (GLXPixmap)d->gpm, (GLXContext)d->cx);
       
   842     } else if (d->paintDevice->devType() == QInternal::Pbuffer) {
       
   843         ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx);
       
   844     } else if (d->paintDevice->devType() == QInternal::Widget) {
       
   845         ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx);
       
   846     }
       
   847     if (!ok)
       
   848         qWarning("QGLContext::makeCurrent(): Failed.");
       
   849 
       
   850     if (ok)
       
   851         QGLContextPrivate::setCurrentContext(this);
       
   852 }
       
   853 
       
   854 void QGLContext::doneCurrent()
       
   855 {
       
   856     Q_D(QGLContext);
       
   857     glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0);
       
   858     QGLContextPrivate::setCurrentContext(0);
       
   859 }
       
   860 
       
   861 
       
   862 void QGLContext::swapBuffers() const
       
   863 {
       
   864     Q_D(const QGLContext);
       
   865     if (!d->valid)
       
   866         return;
       
   867     if (!deviceIsPixmap()) {
       
   868         int interval = d->glFormat.swapInterval();
       
   869         if (interval > 0) {
       
   870             typedef int (*qt_glXGetVideoSyncSGI)(uint *);
       
   871             typedef int (*qt_glXWaitVideoSyncSGI)(int, int, uint *);
       
   872             static qt_glXGetVideoSyncSGI glXGetVideoSyncSGI = 0;
       
   873             static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0;
       
   874             static bool resolved = false;
       
   875             if (!resolved) {
       
   876                 QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
       
   877                 if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
       
   878                     glXGetVideoSyncSGI =  (qt_glXGetVideoSyncSGI)qglx_getProcAddress("glXGetVideoSyncSGI");
       
   879                     glXWaitVideoSyncSGI = (qt_glXWaitVideoSyncSGI)qglx_getProcAddress("glXWaitVideoSyncSGI");
       
   880                 }
       
   881                 resolved = true;
       
   882             }
       
   883             if (glXGetVideoSyncSGI && glXWaitVideoSyncSGI) {
       
   884                 uint counter;
       
   885                 if (!glXGetVideoSyncSGI(&counter))
       
   886                     glXWaitVideoSyncSGI(interval + 1, (counter + interval) % (interval + 1), &counter);
       
   887             }
       
   888         }
       
   889         glXSwapBuffers(qt_x11Info(d->paintDevice)->display(),
       
   890                        static_cast<QWidget *>(d->paintDevice)->winId());
       
   891     }
       
   892 }
       
   893 
       
   894 QColor QGLContext::overlayTransparentColor() const
       
   895 {
       
   896     if (isValid())
       
   897         return Qt::transparent;
       
   898     return QColor();                // Invalid color
       
   899 }
       
   900 
       
   901 static uint qt_transparent_pixel(VisualID id, int screen)
       
   902 {
       
   903     for (int i = 0; i < trans_colors.size(); i++) {
       
   904         if (trans_colors[i].vis == id && trans_colors[i].screen == screen)
       
   905             return trans_colors[i].color;
       
   906     }
       
   907     return 0;
       
   908 }
       
   909 
       
   910 uint QGLContext::colorIndex(const QColor& c) const
       
   911 {
       
   912     Q_D(const QGLContext);
       
   913     int screen = ((XVisualInfo *)d->vi)->screen;
       
   914     QColormap colmap = QColormap::instance(screen);
       
   915     if (isValid()) {
       
   916         if (format().plane() && c == Qt::transparent) {
       
   917             return qt_transparent_pixel(((XVisualInfo *)d->vi)->visualid,
       
   918                                         ((XVisualInfo *)d->vi)->screen);
       
   919         }
       
   920         if (((XVisualInfo*)d->vi)->visualid ==
       
   921              XVisualIDFromVisual((Visual *) QX11Info::appVisual(screen)))
       
   922             return colmap.pixel(c);                // We're using QColor's cmap
       
   923 
       
   924         XVisualInfo *info = (XVisualInfo *) d->vi;
       
   925         CMapEntryHash *hash = cmap_handler()->cmap_hash;
       
   926         CMapEntryHash::ConstIterator it = hash->constFind(long(info->visualid)
       
   927                 + (info->screen * 256));
       
   928         QCMapEntry *x = 0;
       
   929         if (it != hash->constEnd())
       
   930             x = it.value();
       
   931         if (x && !x->alloc) {                // It's a standard colormap
       
   932             int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0);
       
   933             int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0);
       
   934             int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0);
       
   935             uint p = x->scmap.base_pixel
       
   936                      + (rf * x->scmap.red_mult)
       
   937                      + (gf * x->scmap.green_mult)
       
   938                      + (bf * x->scmap.blue_mult);
       
   939             return p;
       
   940         } else {
       
   941             QMap<int, QRgb> &cmap = (*cmap_handler()->qglcmap_hash)[(long)info->visualid];
       
   942 
       
   943             // already in the map?
       
   944             QRgb target = c.rgb();
       
   945             QMap<int, QRgb>::Iterator it = cmap.begin();
       
   946             for (; it != cmap.end(); ++it) {
       
   947                 if ((*it) == target)
       
   948                     return it.key();
       
   949             }
       
   950 
       
   951             // need to alloc color
       
   952             unsigned long plane_mask[2];
       
   953             unsigned long color_map_entry;
       
   954             if (!XAllocColorCells (QX11Info::display(), x->cmap, true, plane_mask, 0,
       
   955                                    &color_map_entry, 1))
       
   956                 return colmap.pixel(c);
       
   957 
       
   958             XColor col;
       
   959             col.flags = DoRed | DoGreen | DoBlue;
       
   960             col.pixel = color_map_entry;
       
   961             col.red   = (ushort)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5);
       
   962             col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5);
       
   963             col.blue  = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5);
       
   964             XStoreColor(QX11Info::display(), x->cmap, &col);
       
   965 
       
   966             cmap.insert(color_map_entry, target);
       
   967             return color_map_entry;
       
   968         }
       
   969     }
       
   970     return 0;
       
   971 }
       
   972 
       
   973 #ifndef QT_NO_FONTCONFIG
       
   974 /*! \internal
       
   975     This is basically a substitute for glxUseXFont() which can only
       
   976     handle XLFD fonts. This version relies on freetype to render the
       
   977     glyphs, but it works with all fonts that fontconfig provides - both
       
   978     antialiased and aliased bitmap and outline fonts.
       
   979 */
       
   980 static void qgl_use_font(QFontEngineFT *engine, int first, int count, int listBase)
       
   981 {
       
   982     GLfloat color[4];
       
   983     glGetFloatv(GL_CURRENT_COLOR, color);
       
   984 
       
   985     // save the pixel unpack state
       
   986     GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment;
       
   987     glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes);
       
   988     glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst);
       
   989     glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength);
       
   990     glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows);
       
   991     glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels);
       
   992     glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment);
       
   993 
       
   994     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
       
   995     glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
       
   996     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
       
   997     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
       
   998     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
       
   999     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
       
  1000 
       
  1001     const bool antialiased = engine->drawAntialiased();
       
  1002     FT_Face face = engine->lockFace();
       
  1003 
       
  1004     // start generating font glyphs
       
  1005     for (int i = first; i < count; ++i) {
       
  1006         int list = listBase + i;
       
  1007         GLfloat x0, y0, dx, dy;
       
  1008 
       
  1009         FT_Error err;
       
  1010 
       
  1011         err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT);
       
  1012         if (err) {
       
  1013             qDebug("failed loading glyph %d from font", i);
       
  1014             Q_ASSERT(!err);
       
  1015         }
       
  1016         err = FT_Render_Glyph(face->glyph, (antialiased ? FT_RENDER_MODE_NORMAL
       
  1017                                             : FT_RENDER_MODE_MONO));
       
  1018         if (err) {
       
  1019             qDebug("failed rendering glyph %d from font", i);
       
  1020             Q_ASSERT(!err);
       
  1021         }
       
  1022 
       
  1023         FT_Bitmap bm = face->glyph->bitmap;
       
  1024         x0 = face->glyph->metrics.horiBearingX >> 6;
       
  1025         y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6;
       
  1026         dx = face->glyph->metrics.horiAdvance >> 6;
       
  1027         dy = 0;
       
  1028         int sz = bm.pitch * bm.rows;
       
  1029         uint *aa_glyph = 0;
       
  1030         uchar *ua_glyph = 0;
       
  1031 
       
  1032         if (antialiased)
       
  1033             aa_glyph = new uint[sz];
       
  1034         else
       
  1035             ua_glyph = new uchar[sz];
       
  1036 
       
  1037         // convert to GL format
       
  1038         for (int y = 0; y < bm.rows; ++y) {
       
  1039             for (int x = 0; x < bm.pitch; ++x) {
       
  1040                 int c1 = y*bm.pitch + x;
       
  1041                 int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x;
       
  1042                 if (antialiased) {
       
  1043                     aa_glyph[c1] = (int(color[0]*255) << 24)
       
  1044                                    | (int(color[1]*255) << 16)
       
  1045                                    | (int(color[2]*255) << 8) | bm.buffer[c2];
       
  1046                 } else {
       
  1047                     ua_glyph[c1] = bm.buffer[c2];
       
  1048                 }
       
  1049             }
       
  1050         }
       
  1051 
       
  1052         glNewList(list, GL_COMPILE);
       
  1053         if (antialiased) {
       
  1054             // calling glBitmap() is just a trick to move the current
       
  1055             // raster pos, since glGet*() won't work in display lists
       
  1056             glBitmap(0, 0, 0, 0, x0, -y0, 0);
       
  1057             glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph);
       
  1058             glBitmap(0, 0, 0, 0, dx-x0, y0, 0);
       
  1059         } else {
       
  1060             glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph);
       
  1061         }
       
  1062         glEndList();
       
  1063         antialiased ? delete[] aa_glyph : delete[] ua_glyph;
       
  1064     }
       
  1065 
       
  1066     engine->unlockFace();
       
  1067 
       
  1068     // restore pixel unpack settings
       
  1069     glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes);
       
  1070     glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst);
       
  1071     glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength);
       
  1072     glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows);
       
  1073     glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels);
       
  1074     glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment);
       
  1075 }
       
  1076 #endif
       
  1077 
       
  1078 #undef d
       
  1079 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
       
  1080 {
       
  1081     QFont f(fnt);
       
  1082     QFontEngine *engine = f.d->engineForScript(QUnicodeTables::Common);
       
  1083 
       
  1084     if (engine->type() == QFontEngine::Multi)
       
  1085         engine = static_cast<QFontEngineMulti *>(engine)->engine(0);
       
  1086 #ifndef QT_NO_FONTCONFIG
       
  1087     if(engine->type() == QFontEngine::Freetype) {
       
  1088         qgl_use_font(static_cast<QFontEngineFT *>(engine), 0, 256, listBase);
       
  1089         return;
       
  1090     }
       
  1091 #endif
       
  1092     // glXUseXFont() only works with XLFD font structures and a few GL
       
  1093     // drivers crash if 0 is passed as the font handle
       
  1094     f.setStyleStrategy(QFont::OpenGLCompatible);
       
  1095     if (f.handle() && engine->type() == QFontEngine::XLFD)
       
  1096         glXUseXFont(static_cast<Font>(f.handle()), 0, 256, listBase);
       
  1097 }
       
  1098 
       
  1099 void *QGLContext::getProcAddress(const QString &proc) const
       
  1100 {
       
  1101     typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *);
       
  1102     static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
       
  1103     static bool resolved = false;
       
  1104 
       
  1105     if (resolved && !glXGetProcAddressARB)
       
  1106         return 0;
       
  1107     if (!glXGetProcAddressARB) {
       
  1108         QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
       
  1109         if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
       
  1110 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
       
  1111             void *handle = dlopen(NULL, RTLD_LAZY);
       
  1112             if (handle) {
       
  1113                 glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
       
  1114                 dlclose(handle);
       
  1115             }
       
  1116             if (!glXGetProcAddressARB)
       
  1117 #endif
       
  1118             {
       
  1119 #if !defined(QT_NO_LIBRARY)
       
  1120                 extern const QString qt_gl_library_name();
       
  1121                 QLibrary lib(qt_gl_library_name());
       
  1122                 glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
       
  1123 #endif
       
  1124             }
       
  1125         }
       
  1126         resolved = true;
       
  1127     }
       
  1128     if (!glXGetProcAddressARB)
       
  1129         return 0;
       
  1130     return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data()));
       
  1131 }
       
  1132 
       
  1133 /*****************************************************************************
       
  1134   QGLOverlayWidget (Internal overlay class for X11)
       
  1135  *****************************************************************************/
       
  1136 
       
  1137 class QGLOverlayWidget : public QGLWidget
       
  1138 {
       
  1139     Q_OBJECT
       
  1140 public:
       
  1141     QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, const QGLWidget* shareWidget=0);
       
  1142 
       
  1143 protected:
       
  1144     void                initializeGL();
       
  1145     void                paintGL();
       
  1146     void                resizeGL(int w, int h);
       
  1147     bool                x11Event(XEvent *e) { return realWidget->x11Event(e); }
       
  1148 
       
  1149 private:
       
  1150     QGLWidget*                realWidget;
       
  1151 
       
  1152 private:
       
  1153     Q_DISABLE_COPY(QGLOverlayWidget)
       
  1154 };
       
  1155 
       
  1156 
       
  1157 QGLOverlayWidget::QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent,
       
  1158                                    const QGLWidget* shareWidget)
       
  1159     : QGLWidget(format, parent, shareWidget ? shareWidget->d_func()->olw : 0)
       
  1160 {
       
  1161     setAttribute(Qt::WA_X11OpenGLOverlay);
       
  1162     realWidget = parent;
       
  1163 }
       
  1164 
       
  1165 
       
  1166 
       
  1167 void QGLOverlayWidget::initializeGL()
       
  1168 {
       
  1169     QColor transparentColor = context()->overlayTransparentColor();
       
  1170     if (transparentColor.isValid())
       
  1171         qglClearColor(transparentColor);
       
  1172     else
       
  1173         qWarning("QGLOverlayWidget::initializeGL(): Could not get transparent color");
       
  1174     realWidget->initializeOverlayGL();
       
  1175 }
       
  1176 
       
  1177 
       
  1178 void QGLOverlayWidget::resizeGL(int w, int h)
       
  1179 {
       
  1180     glViewport(0, 0, w, h);
       
  1181     realWidget->resizeOverlayGL(w, h);
       
  1182 }
       
  1183 
       
  1184 
       
  1185 void QGLOverlayWidget::paintGL()
       
  1186 {
       
  1187     realWidget->paintOverlayGL();
       
  1188 }
       
  1189 
       
  1190 #undef Bool
       
  1191 QT_BEGIN_INCLUDE_NAMESPACE
       
  1192 #include "qgl_x11.moc"
       
  1193 QT_END_INCLUDE_NAMESPACE
       
  1194 
       
  1195 /*****************************************************************************
       
  1196   QGLWidget UNIX/GLX-specific code
       
  1197  *****************************************************************************/
       
  1198 void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
       
  1199 {
       
  1200     Q_Q(QGLWidget);
       
  1201     initContext(context, shareWidget);
       
  1202     olw = 0;
       
  1203 
       
  1204     if (q->isValid() && context->format().hasOverlay()) {
       
  1205         QString olwName = q->objectName();
       
  1206         olwName += QLatin1String("-QGL_internal_overlay_widget");
       
  1207         olw = new QGLOverlayWidget(QGLFormat::defaultOverlayFormat(), q, shareWidget);
       
  1208         olw->setObjectName(olwName);
       
  1209         if (olw->isValid()) {
       
  1210             olw->setAutoBufferSwap(false);
       
  1211             olw->setFocusProxy(q);
       
  1212         }
       
  1213         else {
       
  1214             delete olw;
       
  1215             olw = 0;
       
  1216             glcx->d_func()->glFormat.setOverlay(false);
       
  1217         }
       
  1218     }
       
  1219 }
       
  1220 
       
  1221 bool QGLWidgetPrivate::renderCxPm(QPixmap* pm)
       
  1222 {
       
  1223     Q_Q(QGLWidget);
       
  1224     if (((XVisualInfo*)glcx->d_func()->vi)->depth != pm->depth())
       
  1225         return false;
       
  1226 
       
  1227     GLXPixmap glPm;
       
  1228 #if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT)
       
  1229     glPm = glXCreateGLXPixmapMESA(X11->display,
       
  1230                                    (XVisualInfo*)glcx->vi,
       
  1231                                    (Pixmap)pm->handle(),
       
  1232                                    qt_gl_choose_cmap(pm->X11->display,
       
  1233                                                 (XVisualInfo*)glcx->vi));
       
  1234 #else
       
  1235     glPm = (quint32)glXCreateGLXPixmap(X11->display,
       
  1236                                          (XVisualInfo*)glcx->d_func()->vi,
       
  1237                                          (Pixmap)pm->handle());
       
  1238 #endif
       
  1239 
       
  1240     if (!glXMakeCurrent(X11->display, glPm, (GLXContext)glcx->d_func()->cx)) {
       
  1241         glXDestroyGLXPixmap(X11->display, glPm);
       
  1242         return false;
       
  1243     }
       
  1244 
       
  1245     glDrawBuffer(GL_FRONT);
       
  1246     if (!glcx->initialized())
       
  1247         q->glInit();
       
  1248     q->resizeGL(pm->width(), pm->height());
       
  1249     q->paintGL();
       
  1250     glFlush();
       
  1251     q->makeCurrent();
       
  1252     glXDestroyGLXPixmap(X11->display, glPm);
       
  1253     q->resizeGL(q->width(), q->height());
       
  1254     return true;
       
  1255 }
       
  1256 
       
  1257 /*! \internal
       
  1258   Free up any allocated colormaps. This fn is only called for
       
  1259   top-level widgets.
       
  1260 */
       
  1261 void QGLWidgetPrivate::cleanupColormaps()
       
  1262 {
       
  1263     if (!cmap.handle()) {
       
  1264         return;
       
  1265     } else {
       
  1266         XFreeColormap(X11->display, (Colormap) cmap.handle());
       
  1267         cmap.setHandle(0);
       
  1268     }
       
  1269 }
       
  1270 
       
  1271 void QGLWidget::setMouseTracking(bool enable)
       
  1272 {
       
  1273     Q_D(QGLWidget);
       
  1274     if (d->olw)
       
  1275         d->olw->setMouseTracking(enable);
       
  1276     QWidget::setMouseTracking(enable);
       
  1277 }
       
  1278 
       
  1279 
       
  1280 void QGLWidget::resizeEvent(QResizeEvent *)
       
  1281 {
       
  1282     Q_D(QGLWidget);
       
  1283     if (!isValid())
       
  1284         return;
       
  1285     makeCurrent();
       
  1286     if (!d->glcx->initialized())
       
  1287         glInit();
       
  1288     glXWaitX();
       
  1289     resizeGL(width(), height());
       
  1290     if (d->olw)
       
  1291         d->olw->setGeometry(rect());
       
  1292 }
       
  1293 
       
  1294 const QGLContext* QGLWidget::overlayContext() const
       
  1295 {
       
  1296     Q_D(const QGLWidget);
       
  1297     if (d->olw)
       
  1298         return d->olw->context();
       
  1299     else
       
  1300         return 0;
       
  1301 }
       
  1302 
       
  1303 
       
  1304 void QGLWidget::makeOverlayCurrent()
       
  1305 {
       
  1306     Q_D(QGLWidget);
       
  1307     if (d->olw)
       
  1308         d->olw->makeCurrent();
       
  1309 }
       
  1310 
       
  1311 
       
  1312 void QGLWidget::updateOverlayGL()
       
  1313 {
       
  1314     Q_D(QGLWidget);
       
  1315     if (d->olw)
       
  1316         d->olw->updateGL();
       
  1317 }
       
  1318 
       
  1319 /*!
       
  1320     \internal
       
  1321 
       
  1322     Sets a new QGLContext, \a context, for this QGLWidget, using the
       
  1323     shared context, \a shareContext. If \a deleteOldContext is true,
       
  1324     the original context is deleted; otherwise it is overridden.
       
  1325 */
       
  1326 void QGLWidget::setContext(QGLContext *context,
       
  1327                             const QGLContext* shareContext,
       
  1328                             bool deleteOldContext)
       
  1329 {
       
  1330     Q_D(QGLWidget);
       
  1331     if (context == 0) {
       
  1332         qWarning("QGLWidget::setContext: Cannot set null context");
       
  1333         return;
       
  1334     }
       
  1335     if (!context->deviceIsPixmap() && context->device() != this) {
       
  1336         qWarning("QGLWidget::setContext: Context must refer to this widget");
       
  1337         return;
       
  1338     }
       
  1339 
       
  1340     if (d->glcx)
       
  1341         d->glcx->doneCurrent();
       
  1342     QGLContext* oldcx = d->glcx;
       
  1343     d->glcx = context;
       
  1344 
       
  1345     if (parentWidget()) {
       
  1346         // force creation of delay-created widgets
       
  1347         parentWidget()->winId();
       
  1348         if (parentWidget()->x11Info().screen() != x11Info().screen())
       
  1349             d_func()->xinfo = parentWidget()->d_func()->xinfo;
       
  1350     }
       
  1351 
       
  1352     // If the application has set WA_TranslucentBackground and not explicitly set
       
  1353     // the alpha buffer size to zero, modify the format so it have an alpha channel
       
  1354     QGLFormat& fmt = d->glcx->d_func()->glFormat;
       
  1355     if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1)
       
  1356         fmt.setAlphaBufferSize(1);
       
  1357 
       
  1358     bool createFailed = false;
       
  1359     if (!d->glcx->isValid()) {
       
  1360         if (!d->glcx->create(shareContext ? shareContext : oldcx))
       
  1361             createFailed = true;
       
  1362     }
       
  1363     if (createFailed) {
       
  1364         if (deleteOldContext)
       
  1365             delete oldcx;
       
  1366         return;
       
  1367     }
       
  1368 
       
  1369     if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
       
  1370         if (deleteOldContext)
       
  1371             delete oldcx;
       
  1372         return;
       
  1373     }
       
  1374 
       
  1375     bool visible = isVisible();
       
  1376     if (visible)
       
  1377         hide();
       
  1378 
       
  1379     XVisualInfo *vi = (XVisualInfo*)d->glcx->d_func()->vi;
       
  1380     XSetWindowAttributes a;
       
  1381 
       
  1382     QColormap colmap = QColormap::instance(vi->screen);
       
  1383     a.colormap = qt_gl_choose_cmap(QX11Info::display(), vi);        // find best colormap
       
  1384     a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
       
  1385     a.border_pixel = colmap.pixel(Qt::black);
       
  1386     Window p = RootWindow(X11->display, vi->screen);
       
  1387     if (parentWidget())
       
  1388         p = parentWidget()->winId();
       
  1389 
       
  1390     Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
       
  1391                               0, vi->depth, InputOutput, vi->visual,
       
  1392                               CWBackPixel|CWBorderPixel|CWColormap, &a);
       
  1393     Window *cmw;
       
  1394     Window *cmwret;
       
  1395     int count;
       
  1396     if (XGetWMColormapWindows(X11->display, window()->winId(),
       
  1397                                 &cmwret, &count)) {
       
  1398         cmw = new Window[count+1];
       
  1399         memcpy((char *)cmw, (char *)cmwret, sizeof(Window)*count);
       
  1400         XFree((char *)cmwret);
       
  1401         int i;
       
  1402         for (i=0; i<count; i++) {
       
  1403             if (cmw[i] == winId()) {                // replace old window
       
  1404                 cmw[i] = w;
       
  1405                 break;
       
  1406             }
       
  1407         }
       
  1408         if (i >= count)                        // append new window
       
  1409             cmw[count++] = w;
       
  1410     } else {
       
  1411         count = 1;
       
  1412         cmw = new Window[count];
       
  1413         cmw[0] = w;
       
  1414     }
       
  1415 
       
  1416 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
       
  1417     if (oldcx && oldcx->windowCreated())
       
  1418         glXReleaseBuffersMESA(X11->display, winId());
       
  1419 #endif
       
  1420     if (deleteOldContext)
       
  1421         delete oldcx;
       
  1422     oldcx = 0;
       
  1423 
       
  1424     if (testAttribute(Qt::WA_WState_Created))
       
  1425         create(w);
       
  1426     else
       
  1427         d->createWinId(w);
       
  1428     XSetWMColormapWindows(X11->display, window()->winId(), cmw, count);
       
  1429     delete [] cmw;
       
  1430 
       
  1431     // calling QWidget::create() will always result in a new paint
       
  1432     // engine being created - get rid of it and replace it with our
       
  1433     // own
       
  1434 
       
  1435     if (visible)
       
  1436         show();
       
  1437     XFlush(X11->display);
       
  1438     d->glcx->setWindowCreated(true);
       
  1439 }
       
  1440 
       
  1441 const QGLColormap & QGLWidget::colormap() const
       
  1442 {
       
  1443     Q_D(const QGLWidget);
       
  1444     return d->cmap;
       
  1445 }
       
  1446 
       
  1447 /*\internal
       
  1448   Store color values in the given colormap.
       
  1449 */
       
  1450 static void qStoreColors(QWidget * tlw, Colormap cmap,
       
  1451                           const QGLColormap & cols)
       
  1452 {
       
  1453     Q_UNUSED(tlw);
       
  1454     XColor c;
       
  1455     QRgb color;
       
  1456 
       
  1457     for (int i = 0; i < cols.size(); i++) {
       
  1458         color = cols.entryRgb(i);
       
  1459         c.pixel = i;
       
  1460         c.red   = (ushort)((qRed(color) / 255.0) * 65535.0 + 0.5);
       
  1461         c.green = (ushort)((qGreen(color) / 255.0) * 65535.0 + 0.5);
       
  1462         c.blue  = (ushort)((qBlue(color) / 255.0) * 65535.0 + 0.5);
       
  1463         c.flags = DoRed | DoGreen | DoBlue;
       
  1464         XStoreColor(X11->display, cmap, &c);
       
  1465     }
       
  1466 }
       
  1467 
       
  1468 /*\internal
       
  1469   Check whether the given visual supports dynamic colormaps or not.
       
  1470 */
       
  1471 static bool qCanAllocColors(QWidget * w)
       
  1472 {
       
  1473     bool validVisual = false;
       
  1474     int  numVisuals;
       
  1475     long mask;
       
  1476     XVisualInfo templ;
       
  1477     XVisualInfo * visuals;
       
  1478     VisualID id = XVisualIDFromVisual((Visual *) w->window()->x11Info().visual());
       
  1479 
       
  1480     mask = VisualScreenMask;
       
  1481     templ.screen = w->x11Info().screen();
       
  1482     visuals = XGetVisualInfo(X11->display, mask, &templ, &numVisuals);
       
  1483 
       
  1484     for (int i = 0; i < numVisuals; i++) {
       
  1485         if (visuals[i].visualid == id) {
       
  1486             switch (visuals[i].c_class) {
       
  1487                 case TrueColor:
       
  1488                 case StaticColor:
       
  1489                 case StaticGray:
       
  1490                 case XGrayScale:
       
  1491                     validVisual = false;
       
  1492                     break;
       
  1493                 case DirectColor:
       
  1494                 case PseudoColor:
       
  1495                     validVisual = true;
       
  1496                     break;
       
  1497             }
       
  1498             break;
       
  1499         }
       
  1500     }
       
  1501     XFree(visuals);
       
  1502 
       
  1503     if (!validVisual)
       
  1504         return false;
       
  1505     return true;
       
  1506 }
       
  1507 
       
  1508 
       
  1509 void QGLWidget::setColormap(const QGLColormap & c)
       
  1510 {
       
  1511     Q_D(QGLWidget);
       
  1512     QWidget * tlw = window(); // must return a valid widget
       
  1513 
       
  1514     d->cmap = c;
       
  1515     if (!d->cmap.handle())
       
  1516         return;
       
  1517 
       
  1518     if (!qCanAllocColors(this)) {
       
  1519         qWarning("QGLWidget::setColormap: Cannot create a read/write "
       
  1520                   "colormap for this visual");
       
  1521         return;
       
  1522     }
       
  1523 
       
  1524     // If the child GL widget is not of the same visual class as the
       
  1525     // toplevel widget we will get in trouble..
       
  1526     Window wid = tlw->winId();
       
  1527     Visual * vis = (Visual *) tlw->x11Info().visual();;
       
  1528     VisualID cvId = XVisualIDFromVisual((Visual *) x11Info().visual());
       
  1529     VisualID tvId = XVisualIDFromVisual((Visual *) tlw->x11Info().visual());
       
  1530     if (cvId != tvId) {
       
  1531         wid = winId();
       
  1532         vis = (Visual *) x11Info().visual();
       
  1533     }
       
  1534 
       
  1535     if (!d->cmap.handle()) // allocate a cmap if necessary
       
  1536         d->cmap.setHandle(XCreateColormap(X11->display, wid, vis, AllocAll));
       
  1537 
       
  1538     qStoreColors(this, (Colormap) d->cmap.handle(), c);
       
  1539     XSetWindowColormap(X11->display, wid, (Colormap) d->cmap.handle());
       
  1540 
       
  1541     // tell the wm that this window has a special colormap
       
  1542     Window * cmw;
       
  1543     Window * cmwret;
       
  1544     int count;
       
  1545     if (XGetWMColormapWindows(X11->display, tlw->winId(), &cmwret, &count))
       
  1546     {
       
  1547         cmw = new Window[count+1];
       
  1548         memcpy((char *) cmw, (char *) cmwret, sizeof(Window) * count);
       
  1549         XFree((char *) cmwret);
       
  1550         int i;
       
  1551         for (i = 0; i < count; i++) {
       
  1552             if (cmw[i] == winId()) {
       
  1553                 break;
       
  1554             }
       
  1555         }
       
  1556         if (i >= count)   // append new window only if not in the list
       
  1557             cmw[count++] = winId();
       
  1558     } else {
       
  1559         count = 1;
       
  1560         cmw = new Window[count];
       
  1561         cmw[0] = winId();
       
  1562     }
       
  1563     XSetWMColormapWindows(X11->display, tlw->winId(), cmw, count);
       
  1564     delete [] cmw;
       
  1565 }
       
  1566 
       
  1567 void QGLExtensions::init()
       
  1568 {
       
  1569     static bool init_done = false;
       
  1570 
       
  1571     if (init_done)
       
  1572         return;
       
  1573     init_done = true;
       
  1574 
       
  1575     QGLWidget dmy;
       
  1576     dmy.makeCurrent();
       
  1577     init_extensions();
       
  1578 
       
  1579     // nvidia 9x.xx unix drivers contain a bug which requires us to call glFinish before releasing an fbo
       
  1580     // to avoid painting artifacts
       
  1581     const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
       
  1582     const int pos = versionString.indexOf("NVIDIA");
       
  1583     if (pos >= 0) {
       
  1584         const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
       
  1585         nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
       
  1586     }
       
  1587 }
       
  1588 
       
  1589 // Solaris defines glXBindTexImageEXT as part of the GL library
       
  1590 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
  1591 typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
       
  1592 typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int);
       
  1593 static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
       
  1594 static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0;
       
  1595 
       
  1596 bool qt_resolveTextureFromPixmap()
       
  1597 {
       
  1598     static bool resolvedTextureFromPixmap = false;
       
  1599 
       
  1600     if (!resolvedTextureFromPixmap) {
       
  1601         resolvedTextureFromPixmap = true;
       
  1602 
       
  1603         // Check to see if we have NPOT texture support
       
  1604         if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
       
  1605              !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
       
  1606         {
       
  1607             return false; // Can't use TFP without NPOT
       
  1608         }
       
  1609 
       
  1610         QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
       
  1611         if (glxExt.contains(QLatin1String("GLX_EXT_texture_from_pixmap"))) {
       
  1612             glXBindTexImageEXT = (qt_glXBindTexImageEXT) qglx_getProcAddress("glXBindTexImageEXT");
       
  1613             glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) qglx_getProcAddress("glXReleaseTexImageEXT");
       
  1614         }
       
  1615     }
       
  1616 
       
  1617     return glXBindTexImageEXT && glXReleaseTexImageEXT;
       
  1618 }
       
  1619 #endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
  1620 
       
  1621 
       
  1622 QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key,
       
  1623                                                            QGLContext::BindOptions options)
       
  1624 {
       
  1625 #if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
       
  1626     return 0;
       
  1627 #else
       
  1628     Q_Q(QGLContext);
       
  1629 
       
  1630     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
       
  1631 
       
  1632     if (!qt_resolveTextureFromPixmap())
       
  1633         return 0;
       
  1634 
       
  1635     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
       
  1636     const QX11Info &x11Info = pixmapData->xinfo;
       
  1637 
       
  1638     // Store the configs (Can be static because configs aren't dependent on current context)
       
  1639     static GLXFBConfig glxRGBPixmapConfig = 0;
       
  1640     static bool RGBConfigInverted = false;
       
  1641     static GLXFBConfig glxRGBAPixmapConfig = 0;
       
  1642     static bool RGBAConfigInverted = false;
       
  1643 
       
  1644     bool hasAlpha = pixmapData->hasAlphaChannel();
       
  1645 
       
  1646     // Check to see if we need a config
       
  1647     if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) {
       
  1648         GLXFBConfig    *configList = 0;
       
  1649         int             configCount = 0;
       
  1650 
       
  1651         int configAttribs[] = {
       
  1652             hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
       
  1653             GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
       
  1654             GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
       
  1655             // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
       
  1656             GLX_Y_INVERTED_EXT, options & QGLContext::CanFlipNativePixmapBindOption ? GLX_DONT_CARE : False,
       
  1657             XNone
       
  1658         };
       
  1659         configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount);
       
  1660         if (!configList)
       
  1661             return 0;
       
  1662 
       
  1663         int yInv;
       
  1664         glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv);
       
  1665 
       
  1666         if (hasAlpha) {
       
  1667             glxRGBAPixmapConfig = configList[0];
       
  1668             RGBAConfigInverted = yInv;
       
  1669         }
       
  1670         else {
       
  1671             glxRGBPixmapConfig = configList[0];
       
  1672             RGBConfigInverted = yInv;
       
  1673         }
       
  1674 
       
  1675         XFree(configList);
       
  1676     }
       
  1677 
       
  1678     // Check to see if the surface is still valid
       
  1679     if (pixmapData->gl_surface &&
       
  1680         hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
       
  1681     {
       
  1682         // Surface is invalid!
       
  1683         destroyGlSurfaceForPixmap(pixmapData);
       
  1684     }
       
  1685 
       
  1686     // Check to see if we need a surface
       
  1687     if (!pixmapData->gl_surface) {
       
  1688         GLXPixmap glxPixmap;
       
  1689         int pixmapAttribs[] = {
       
  1690             GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
       
  1691             GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
       
  1692             GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care
       
  1693             XNone
       
  1694         };
       
  1695 
       
  1696         // Wrap the X Pixmap into a GLXPixmap:
       
  1697         glxPixmap = glXCreatePixmap(x11Info.display(),
       
  1698                                     hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig,
       
  1699                                     pixmapData->handle(), pixmapAttribs);
       
  1700 
       
  1701         if (!glxPixmap)
       
  1702             return 0;
       
  1703 
       
  1704         pixmapData->gl_surface = (Qt::HANDLE)glxPixmap;
       
  1705 
       
  1706         // Make sure the cleanup hook gets called so we can delete the glx pixmap
       
  1707         pixmapData->is_cached = true;
       
  1708     }
       
  1709 
       
  1710     GLuint textureId;
       
  1711     glGenTextures(1, &textureId);
       
  1712     glBindTexture(GL_TEXTURE_2D, textureId);
       
  1713     glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0);
       
  1714 
       
  1715     glBindTexture(GL_TEXTURE_2D, textureId);
       
  1716 
       
  1717     if (!((hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted)))
       
  1718         options &= ~QGLContext::InvertedYBindOption;
       
  1719 
       
  1720     QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
       
  1721     if (texture->options & QGLContext::InvertedYBindOption)
       
  1722         pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
       
  1723 
       
  1724     // We assume the cost of bound pixmaps is zero
       
  1725     QGLTextureCache::instance()->insert(q, key, texture, 0);
       
  1726 
       
  1727     return texture;
       
  1728 #endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
       
  1729 }
       
  1730 
       
  1731 
       
  1732 void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
       
  1733 {
       
  1734 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
  1735     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
       
  1736     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
       
  1737     if (pixmapData->gl_surface) {
       
  1738         glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface);
       
  1739         pixmapData->gl_surface = 0;
       
  1740     }
       
  1741 #endif
       
  1742 }
       
  1743 
       
  1744 void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
       
  1745 {
       
  1746 #if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
       
  1747     Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
       
  1748     Q_ASSERT(QGLContext::currentContext());
       
  1749     QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
       
  1750     if (pixmapData->gl_surface)
       
  1751         glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT);
       
  1752 #endif
       
  1753 }
       
  1754 
       
  1755 QT_END_NAMESPACE