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