src/opengl/qgl_win.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 
       
    43 #include <qgl.h>
       
    44 #include <qlist.h>
       
    45 #include <qmap.h>
       
    46 #include <qpixmap.h>
       
    47 #include <qevent.h>
       
    48 #include <private/qgl_p.h>
       
    49 #include <qcolormap.h>
       
    50 #include <qvarlengtharray.h>
       
    51 #include <qdebug.h>
       
    52 #include <qcolor.h>
       
    53 
       
    54 #include <qt_windows.h>
       
    55 
       
    56 typedef bool (APIENTRY *PFNWGLGETPIXELFORMATATTRIBIVARB)(HDC hdc,
       
    57                                                          int iPixelFormat,
       
    58                                                          int iLayerPlane,
       
    59                                                          uint nAttributes,
       
    60                                                          const int *piAttributes,
       
    61                                                          int *piValues);
       
    62 typedef bool (APIENTRY *PFNWGLCHOOSEPIXELFORMATARB)(HDC hdc,
       
    63                                                     const int *piAttribList,
       
    64                                                     const float *pfAttribFList,
       
    65                                                     uint nMaxFormats,
       
    66                                                     int *piFormats,
       
    67                                                     UINT *nNumFormats);
       
    68 #ifndef WGL_ARB_multisample
       
    69 #define WGL_SAMPLE_BUFFERS_ARB               0x2041
       
    70 #define WGL_SAMPLES_ARB                      0x2042
       
    71 #endif
       
    72 
       
    73 #ifndef WGL_ARB_pixel_format
       
    74 #define WGL_NUMBER_PIXEL_FORMATS_ARB   0x2000
       
    75 #define WGL_DRAW_TO_WINDOW_ARB         0x2001
       
    76 #define WGL_DRAW_TO_BITMAP_ARB         0x2002
       
    77 #define WGL_ACCELERATION_ARB           0x2003
       
    78 #define WGL_NEED_PALETTE_ARB           0x2004
       
    79 #define WGL_NEED_SYSTEM_PALETTE_ARB    0x2005
       
    80 #define WGL_SWAP_LAYER_BUFFERS_ARB     0x2006
       
    81 #define WGL_SWAP_METHOD_ARB            0x2007
       
    82 #define WGL_NUMBER_OVERLAYS_ARB        0x2008
       
    83 #define WGL_NUMBER_UNDERLAYS_ARB       0x2009
       
    84 #define WGL_TRANSPARENT_ARB            0x200A
       
    85 #define WGL_TRANSPARENT_RED_VALUE_ARB  0x2037
       
    86 #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
       
    87 #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
       
    88 #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
       
    89 #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
       
    90 #define WGL_SHARE_DEPTH_ARB            0x200C
       
    91 #define WGL_SHARE_STENCIL_ARB          0x200D
       
    92 #define WGL_SHARE_ACCUM_ARB            0x200E
       
    93 #define WGL_SUPPORT_GDI_ARB            0x200F
       
    94 #define WGL_SUPPORT_OPENGL_ARB         0x2010
       
    95 #define WGL_DOUBLE_BUFFER_ARB          0x2011
       
    96 #define WGL_STEREO_ARB                 0x2012
       
    97 #define WGL_PIXEL_TYPE_ARB             0x2013
       
    98 #define WGL_COLOR_BITS_ARB             0x2014
       
    99 #define WGL_RED_BITS_ARB               0x2015
       
   100 #define WGL_RED_SHIFT_ARB              0x2016
       
   101 #define WGL_GREEN_BITS_ARB             0x2017
       
   102 #define WGL_GREEN_SHIFT_ARB            0x2018
       
   103 #define WGL_BLUE_BITS_ARB              0x2019
       
   104 #define WGL_BLUE_SHIFT_ARB             0x201A
       
   105 #define WGL_ALPHA_BITS_ARB             0x201B
       
   106 #define WGL_ALPHA_SHIFT_ARB            0x201C
       
   107 #define WGL_ACCUM_BITS_ARB             0x201D
       
   108 #define WGL_ACCUM_RED_BITS_ARB         0x201E
       
   109 #define WGL_ACCUM_GREEN_BITS_ARB       0x201F
       
   110 #define WGL_ACCUM_BLUE_BITS_ARB        0x2020
       
   111 #define WGL_ACCUM_ALPHA_BITS_ARB       0x2021
       
   112 #define WGL_DEPTH_BITS_ARB             0x2022
       
   113 #define WGL_STENCIL_BITS_ARB           0x2023
       
   114 #define WGL_AUX_BUFFERS_ARB            0x2024
       
   115 #define WGL_NO_ACCELERATION_ARB        0x2025
       
   116 #define WGL_GENERIC_ACCELERATION_ARB   0x2026
       
   117 #define WGL_FULL_ACCELERATION_ARB      0x2027
       
   118 #define WGL_SWAP_EXCHANGE_ARB          0x2028
       
   119 #define WGL_SWAP_COPY_ARB              0x2029
       
   120 #define WGL_SWAP_UNDEFINED_ARB         0x202A
       
   121 #define WGL_TYPE_RGBA_ARB              0x202B
       
   122 #define WGL_TYPE_COLORINDEX_ARB        0x202C
       
   123 #endif
       
   124 
       
   125 QT_BEGIN_NAMESPACE
       
   126 
       
   127 class QGLCmapPrivate
       
   128 {
       
   129 public:
       
   130     QGLCmapPrivate() : count(1) { }
       
   131     void ref()                { ++count; }
       
   132     bool deref()        { return !--count; }
       
   133     uint count;
       
   134 
       
   135     enum AllocState{ UnAllocated = 0, Allocated = 0x01, Reserved = 0x02 };
       
   136 
       
   137     int maxSize;
       
   138     QVector<uint> colorArray;
       
   139     QVector<quint8> allocArray;
       
   140     QVector<quint8> contextArray;
       
   141     QMap<uint,int> colorMap;
       
   142 };
       
   143 
       
   144 /*****************************************************************************
       
   145   QColorMap class - temporarily here, until it is ready for prime time
       
   146  *****************************************************************************/
       
   147 
       
   148 /****************************************************************************
       
   149 **
       
   150 ** Definition of QColorMap class
       
   151 **
       
   152 ****************************************************************************/
       
   153 
       
   154 class QGLCmapPrivate;
       
   155 
       
   156 class /*Q_EXPORT*/ QGLCmap
       
   157 {
       
   158 public:
       
   159     enum Flags { Reserved = 0x01 };
       
   160 
       
   161     QGLCmap(int maxSize = 256);
       
   162     QGLCmap(const QGLCmap& map);
       
   163     ~QGLCmap();
       
   164 
       
   165     QGLCmap& operator=(const QGLCmap& map);
       
   166 
       
   167     // isEmpty and/or isNull ?
       
   168     int size() const;
       
   169     int maxSize() const;
       
   170 
       
   171     void resize(int newSize);
       
   172 
       
   173     int find(QRgb color) const;
       
   174     int findNearest(QRgb color) const;
       
   175     int allocate(QRgb color, uint flags = 0, quint8 context = 0);
       
   176 
       
   177     void setEntry(int idx, QRgb color, uint flags = 0, quint8 context = 0);
       
   178 
       
   179     const QRgb* colors() const;
       
   180 
       
   181 private:
       
   182     void detach();
       
   183     QGLCmapPrivate* d;
       
   184 };
       
   185 
       
   186 
       
   187 QGLCmap::QGLCmap(int maxSize) // add a bool prealloc?
       
   188 {
       
   189     d = new QGLCmapPrivate;
       
   190     d->maxSize = maxSize;
       
   191 }
       
   192 
       
   193 
       
   194 QGLCmap::QGLCmap(const QGLCmap& map)
       
   195 {
       
   196     d = map.d;
       
   197     d->ref();
       
   198 }
       
   199 
       
   200 
       
   201 QGLCmap::~QGLCmap()
       
   202 {
       
   203     if (d && d->deref())
       
   204         delete d;
       
   205     d = 0;
       
   206 }
       
   207 
       
   208 
       
   209 QGLCmap& QGLCmap::operator=(const QGLCmap& map)
       
   210 {
       
   211     map.d->ref();
       
   212     if (d->deref())
       
   213         delete d;
       
   214     d = map.d;
       
   215     return *this;
       
   216 }
       
   217 
       
   218 
       
   219 int QGLCmap::size() const
       
   220 {
       
   221     return d->colorArray.size();
       
   222 }
       
   223 
       
   224 
       
   225 int QGLCmap::maxSize() const
       
   226 {
       
   227     return d->maxSize;
       
   228 }
       
   229 
       
   230 
       
   231 void QGLCmap::detach()
       
   232 {
       
   233     if (d->count != 1) {
       
   234         d->deref();
       
   235         QGLCmapPrivate* newd = new QGLCmapPrivate;
       
   236         newd->maxSize = d->maxSize;
       
   237         newd->colorArray = d->colorArray;
       
   238         newd->allocArray = d->allocArray;
       
   239         newd->contextArray = d->contextArray;
       
   240         newd->colorArray.detach();
       
   241         newd->allocArray.detach();
       
   242         newd->contextArray.detach();
       
   243         newd->colorMap = d->colorMap;
       
   244         d = newd;
       
   245     }
       
   246 }
       
   247 
       
   248 
       
   249 void QGLCmap::resize(int newSize)
       
   250 {
       
   251     if (newSize < 0 || newSize > d->maxSize) {
       
   252         qWarning("QGLCmap::resize(): size out of range");
       
   253         return;
       
   254     }
       
   255     int oldSize = size();
       
   256     detach();
       
   257     //if shrinking; remove the lost elems from colorMap
       
   258     d->colorArray.resize(newSize);
       
   259     d->allocArray.resize(newSize);
       
   260     d->contextArray.resize(newSize);
       
   261     if (newSize > oldSize) {
       
   262         memset(d->allocArray.data() + oldSize, 0, newSize - oldSize);
       
   263         memset(d->contextArray.data() + oldSize, 0, newSize - oldSize);
       
   264     }
       
   265 }
       
   266 
       
   267 
       
   268 int QGLCmap::find(QRgb color) const
       
   269 {
       
   270     QMap<uint,int>::ConstIterator it = d->colorMap.find(color);
       
   271     if (it != d->colorMap.end())
       
   272         return *it;
       
   273     return -1;
       
   274 }
       
   275 
       
   276 
       
   277 int QGLCmap::findNearest(QRgb color) const
       
   278 {
       
   279     int idx = find(color);
       
   280     if (idx >= 0)
       
   281         return idx;
       
   282     int mapSize = size();
       
   283     int mindist = 200000;
       
   284     int r = qRed(color);
       
   285     int g = qGreen(color);
       
   286     int b = qBlue(color);
       
   287     int rx, gx, bx, dist;
       
   288     for (int i=0; i < mapSize; i++) {
       
   289         if (!(d->allocArray[i] & QGLCmapPrivate::Allocated))
       
   290             continue;
       
   291         QRgb ci = d->colorArray[i];
       
   292         rx = r - qRed(ci);
       
   293         gx = g - qGreen(ci);
       
   294         bx = b - qBlue(ci);
       
   295         dist = rx*rx + gx*gx + bx*bx;                // calculate distance
       
   296         if (dist < mindist) {                        // minimal?
       
   297             mindist = dist;
       
   298             idx = i;
       
   299         }
       
   300     }
       
   301     return idx;
       
   302 }
       
   303 
       
   304 
       
   305 
       
   306 
       
   307 // Does not always allocate; returns existing c idx if found
       
   308 
       
   309 int QGLCmap::allocate(QRgb color, uint flags, quint8 context)
       
   310 {
       
   311     int idx = find(color);
       
   312     if (idx >= 0)
       
   313         return idx;
       
   314 
       
   315     int mapSize = d->colorArray.size();
       
   316     int newIdx = d->allocArray.indexOf(QGLCmapPrivate::UnAllocated);
       
   317 
       
   318     if (newIdx < 0) {                        // Must allocate more room
       
   319         if (mapSize < d->maxSize) {
       
   320             newIdx = mapSize;
       
   321             mapSize++;
       
   322             resize(mapSize);
       
   323         }
       
   324         else {
       
   325             //# add a bool param that says what to do in case no more room -
       
   326             // fail (-1) or return nearest?
       
   327             return -1;
       
   328         }
       
   329     }
       
   330 
       
   331     d->colorArray[newIdx] = color;
       
   332     if (flags & QGLCmap::Reserved) {
       
   333         d->allocArray[newIdx] = QGLCmapPrivate::Reserved;
       
   334     }
       
   335     else {
       
   336         d->allocArray[newIdx] = QGLCmapPrivate::Allocated;
       
   337         d->colorMap.insert(color, newIdx);
       
   338     }
       
   339     d->contextArray[newIdx] = context;
       
   340     return newIdx;
       
   341 }
       
   342 
       
   343 
       
   344 void QGLCmap::setEntry(int idx, QRgb color, uint flags, quint8 context)
       
   345 {
       
   346     if (idx < 0 || idx >= d->maxSize) {
       
   347         qWarning("QGLCmap::set(): Index out of range");
       
   348         return;
       
   349     }
       
   350     detach();
       
   351     int mapSize = size();
       
   352     if (idx >= mapSize) {
       
   353         mapSize = idx + 1;
       
   354         resize(mapSize);
       
   355     }
       
   356     d->colorArray[idx] = color;
       
   357     if (flags & QGLCmap::Reserved) {
       
   358         d->allocArray[idx] = QGLCmapPrivate::Reserved;
       
   359     }
       
   360     else {
       
   361         d->allocArray[idx] = QGLCmapPrivate::Allocated;
       
   362         d->colorMap.insert(color, idx);
       
   363     }
       
   364     d->contextArray[idx] = context;
       
   365 }
       
   366 
       
   367 
       
   368 const QRgb* QGLCmap::colors() const
       
   369 {
       
   370     return d->colorArray.data();
       
   371 }
       
   372 
       
   373 
       
   374 
       
   375 /*****************************************************************************
       
   376   QGLFormat Win32/WGL-specific code
       
   377  *****************************************************************************/
       
   378 
       
   379 
       
   380 void qwglError(const char* method, const char* func)
       
   381 {
       
   382 #ifndef QT_NO_DEBUG
       
   383     char* lpMsgBuf;
       
   384     FormatMessageA(
       
   385                   FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       
   386                   0, GetLastError(),
       
   387                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
       
   388                   (char*) &lpMsgBuf, 0, 0);
       
   389     qWarning("%s : %s failed: %s", method, func, lpMsgBuf);
       
   390     LocalFree(lpMsgBuf);
       
   391 #else
       
   392     Q_UNUSED(method);
       
   393     Q_UNUSED(func);
       
   394 #endif
       
   395 }
       
   396 
       
   397 
       
   398 
       
   399 bool QGLFormat::hasOpenGL()
       
   400 {
       
   401     return true;
       
   402 }
       
   403 
       
   404 static bool opengl32dll = false;
       
   405 
       
   406 bool QGLFormat::hasOpenGLOverlays()
       
   407 {
       
   408     // workaround for matrox driver:
       
   409     // make a cheap call to opengl to force loading of DLL
       
   410     if (!opengl32dll) {
       
   411         GLint params;
       
   412         glGetIntegerv(GL_DEPTH_BITS, &params);
       
   413         opengl32dll = true;
       
   414     }
       
   415 
       
   416     static bool checkDone = false;
       
   417     static bool hasOl = false;
       
   418 
       
   419     if (!checkDone) {
       
   420         checkDone = true;
       
   421         HDC display_dc = GetDC(0);
       
   422         int pfiMax = DescribePixelFormat(display_dc, 0, 0, NULL);
       
   423         PIXELFORMATDESCRIPTOR pfd;
       
   424         for (int pfi = 1; pfi <= pfiMax; pfi++) {
       
   425             DescribePixelFormat(display_dc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
       
   426             if ((pfd.bReserved & 0x0f) && (pfd.dwFlags & PFD_SUPPORT_OPENGL)) {
       
   427                 // This format has overlays/underlays
       
   428                 LAYERPLANEDESCRIPTOR lpd;
       
   429                 wglDescribeLayerPlane(display_dc, pfi, 1,
       
   430                                        sizeof(LAYERPLANEDESCRIPTOR), &lpd);
       
   431                 if (lpd.dwFlags & LPD_SUPPORT_OPENGL) {
       
   432                     hasOl = true;
       
   433                     break;
       
   434                 }
       
   435             }
       
   436         }
       
   437         ReleaseDC(0, display_dc);
       
   438     }
       
   439     return hasOl;
       
   440 }
       
   441 
       
   442 
       
   443 /*****************************************************************************
       
   444   QGLContext Win32/WGL-specific code
       
   445  *****************************************************************************/
       
   446 
       
   447 static uchar qgl_rgb_palette_comp(int idx, uint nbits, uint shift)
       
   448 {
       
   449     const uchar map_3_to_8[8] = {
       
   450         0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
       
   451     };
       
   452     const uchar map_2_to_8[4] = {
       
   453         0, 0x55, 0xaa, 0xff
       
   454     };
       
   455     const uchar map_1_to_8[2] = {
       
   456         0, 255
       
   457     };
       
   458 
       
   459     uchar val = (uchar) (idx >> shift);
       
   460     uchar res = 0;
       
   461     switch (nbits) {
       
   462     case 1:
       
   463         val &= 0x1;
       
   464         res =  map_1_to_8[val];
       
   465         break;
       
   466     case 2:
       
   467         val &= 0x3;
       
   468         res = map_2_to_8[val];
       
   469         break;
       
   470     case 3:
       
   471         val &= 0x7;
       
   472         res = map_3_to_8[val];
       
   473         break;
       
   474     default:
       
   475         res = 0;
       
   476     }
       
   477     return res;
       
   478 }
       
   479 
       
   480 
       
   481 static QRgb* qgl_create_rgb_palette(const PIXELFORMATDESCRIPTOR* pfd)
       
   482 {
       
   483     if ((pfd->iPixelType != PFD_TYPE_RGBA) ||
       
   484          !(pfd->dwFlags & PFD_NEED_PALETTE) ||
       
   485          (pfd->cColorBits != 8))
       
   486         return 0;
       
   487     int numEntries = 1 << pfd->cColorBits;
       
   488     QRgb* pal = new QRgb[numEntries];
       
   489     for (int i = 0; i < numEntries; i++) {
       
   490         int r = qgl_rgb_palette_comp(i, pfd->cRedBits, pfd->cRedShift);
       
   491         int g = qgl_rgb_palette_comp(i, pfd->cGreenBits, pfd->cGreenShift);
       
   492         int b = qgl_rgb_palette_comp(i, pfd->cBlueBits, pfd->cBlueShift);
       
   493         pal[i] = qRgb(r, g, b);
       
   494     }
       
   495 
       
   496     const int syscol_indices[12] = {
       
   497         3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
       
   498     };
       
   499 
       
   500     const uint syscols[20] = {
       
   501         0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080,
       
   502         0x008080, 0xc0c0c0, 0xc0dcc0, 0xa6caf0, 0xfffbf0, 0xa0a0a4,
       
   503         0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff,
       
   504         0x00ffff, 0xffffff
       
   505     };        // colors #1 - #12 are not present in pal; gets added below
       
   506 
       
   507     if ((pfd->cColorBits == 8)                                &&
       
   508          (pfd->cRedBits   == 3) && (pfd->cRedShift   == 0)        &&
       
   509          (pfd->cGreenBits == 3) && (pfd->cGreenShift == 3)        &&
       
   510          (pfd->cBlueBits  == 2) && (pfd->cBlueShift  == 6)) {
       
   511         for (int j = 0 ; j < 12 ; j++)
       
   512             pal[syscol_indices[j]] = QRgb(syscols[j+1]);
       
   513     }
       
   514 
       
   515     return pal;
       
   516 }
       
   517 
       
   518 static QGLFormat pfdToQGLFormat(const PIXELFORMATDESCRIPTOR* pfd)
       
   519 {
       
   520     QGLFormat fmt;
       
   521     fmt.setDoubleBuffer(pfd->dwFlags & PFD_DOUBLEBUFFER);
       
   522     fmt.setDepth(pfd->cDepthBits);
       
   523     if (fmt.depth())
       
   524         fmt.setDepthBufferSize(pfd->cDepthBits);
       
   525     fmt.setRgba(pfd->iPixelType == PFD_TYPE_RGBA);
       
   526     fmt.setRedBufferSize(pfd->cRedBits);
       
   527     fmt.setGreenBufferSize(pfd->cGreenBits);
       
   528     fmt.setBlueBufferSize(pfd->cBlueBits);
       
   529     fmt.setAlpha(pfd->cAlphaBits);
       
   530     if (fmt.alpha())
       
   531         fmt.setAlphaBufferSize(pfd->cAlphaBits);
       
   532     fmt.setAccum(pfd->cAccumBits);
       
   533     if (fmt.accum())
       
   534         fmt.setAccumBufferSize(pfd->cAccumRedBits);
       
   535     fmt.setStencil(pfd->cStencilBits);
       
   536     if (fmt.stencil())
       
   537         fmt.setStencilBufferSize(pfd->cStencilBits);
       
   538     fmt.setStereo(pfd->dwFlags & PFD_STEREO);
       
   539     fmt.setDirectRendering((pfd->dwFlags & PFD_GENERIC_ACCELERATED) ||
       
   540                             !(pfd->dwFlags & PFD_GENERIC_FORMAT));
       
   541     fmt.setOverlay((pfd->bReserved & 0x0f) != 0);
       
   542     return fmt;
       
   543 }
       
   544 
       
   545 /*
       
   546    NB! requires a current GL context to work
       
   547 */
       
   548 QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
       
   549 {
       
   550     QGLFormat fmt;
       
   551     QVarLengthArray<int> iAttributes(40);
       
   552     QVarLengthArray<int> iValues(40);
       
   553     int i = 0;
       
   554     bool has_sample_buffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
       
   555 
       
   556     iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0
       
   557     iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1
       
   558     iAttributes[i++] = WGL_PIXEL_TYPE_ARB; // 2
       
   559     iAttributes[i++] = WGL_RED_BITS_ARB; // 3
       
   560     iAttributes[i++] = WGL_GREEN_BITS_ARB; // 4
       
   561     iAttributes[i++] = WGL_BLUE_BITS_ARB; // 5
       
   562     iAttributes[i++] = WGL_ALPHA_BITS_ARB; // 6
       
   563     iAttributes[i++] = WGL_ACCUM_BITS_ARB; // 7
       
   564     iAttributes[i++] = WGL_STENCIL_BITS_ARB; // 8
       
   565     iAttributes[i++] = WGL_STEREO_ARB; // 9
       
   566     iAttributes[i++] = WGL_ACCELERATION_ARB; // 10
       
   567     iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB; // 11
       
   568     if (has_sample_buffers) {
       
   569         iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; // 12
       
   570         iAttributes[i++] = WGL_SAMPLES_ARB; // 13
       
   571     }
       
   572     PFNWGLGETPIXELFORMATATTRIBIVARB wglGetPixelFormatAttribivARB =
       
   573         (PFNWGLGETPIXELFORMATATTRIBIVARB) wglGetProcAddress("wglGetPixelFormatAttribivARB");
       
   574 
       
   575     if (wglGetPixelFormatAttribivARB
       
   576         && wglGetPixelFormatAttribivARB(hdc, pfi, 0, i,
       
   577                                         iAttributes.constData(),
       
   578                                         iValues.data()))
       
   579     {
       
   580         fmt.setDoubleBuffer(iValues[0]);
       
   581         fmt.setDepth(iValues[1]);
       
   582         if (fmt.depth())
       
   583             fmt.setDepthBufferSize(iValues[1]);
       
   584         fmt.setRgba(iValues[2] == WGL_TYPE_RGBA_ARB);
       
   585         fmt.setRedBufferSize(iValues[3]);
       
   586         fmt.setGreenBufferSize(iValues[4]);
       
   587         fmt.setBlueBufferSize(iValues[5]);
       
   588         fmt.setAlpha(iValues[6]);
       
   589         if (fmt.alpha())
       
   590             fmt.setAlphaBufferSize(iValues[6]);
       
   591         fmt.setAccum(iValues[7]);
       
   592         if (fmt.accum())
       
   593             fmt.setAccumBufferSize(iValues[7]);
       
   594         fmt.setStencil(iValues[8]);
       
   595         if (fmt.stencil())
       
   596             fmt.setStencilBufferSize(iValues[8]);
       
   597         fmt.setStereo(iValues[9]);
       
   598         if (iValues[10] == WGL_FULL_ACCELERATION_ARB)
       
   599             fmt.setDirectRendering(true);
       
   600         else
       
   601             fmt.setDirectRendering(false);
       
   602         fmt.setOverlay(iValues[11]);
       
   603         if (has_sample_buffers) {
       
   604             fmt.setSampleBuffers(iValues[12]);
       
   605             if (fmt.sampleBuffers())
       
   606                 fmt.setSamples(iValues[13]);
       
   607         }
       
   608     }
       
   609 #if 0
       
   610     qDebug() << "values for pfi:" << pfi;
       
   611     qDebug() << "doublebuffer  0:" << fmt.doubleBuffer();
       
   612     qDebug() << "depthbuffer   1:" << fmt.depthBufferSize();
       
   613     qDebug() << "rgba          2:" << fmt.rgba();
       
   614     qDebug() << "red size      3:" << fmt.redBufferSize();
       
   615     qDebug() << "green size    4:" << fmt.greenBufferSize();
       
   616     qDebug() << "blue size     5:" << fmt.blueBufferSize();
       
   617     qDebug() << "alpha size    6:" << fmt.alphaBufferSize();
       
   618     qDebug() << "accum size    7:" << fmt.accumBufferSize();
       
   619     qDebug() << "stencil size  8:" << fmt.stencilBufferSize();
       
   620     qDebug() << "stereo        9:" << fmt.stereo();
       
   621     qDebug() << "direct       10:" << fmt.directRendering();
       
   622     qDebug() << "has overlays 11:" << fmt.hasOverlay();
       
   623     qDebug() << "sample buff  12:" << fmt.sampleBuffers();
       
   624     qDebug() << "num samples  13:" << fmt.samples();
       
   625 #endif
       
   626     return fmt;
       
   627 }
       
   628 
       
   629 
       
   630 /*
       
   631    Creates a temporary GL context and makes it current
       
   632    - cleans up when the object is destructed.
       
   633 */
       
   634 
       
   635 Q_GUI_EXPORT const QString qt_getRegisteredWndClass();
       
   636 
       
   637 class QGLTempContext
       
   638 {
       
   639 public:
       
   640     QGLTempContext(bool directRendering, QWidget *parent = 0)
       
   641     {
       
   642         QString windowClassName = qt_getRegisteredWndClass();
       
   643         if (parent && !parent->internalWinId())
       
   644             parent = parent->nativeParentWidget();
       
   645 
       
   646         dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
       
   647                               0, 0, 0, 0, 1, 1,
       
   648                               parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
       
   649 
       
   650         dmy_pdc = GetDC(dmy_id);
       
   651         PIXELFORMATDESCRIPTOR dmy_pfd;
       
   652         memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
       
   653         dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
       
   654         dmy_pfd.nVersion = 1;
       
   655         dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
       
   656         dmy_pfd.iPixelType = PFD_TYPE_RGBA;
       
   657         if (!directRendering)
       
   658             dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
       
   659 
       
   660         int dmy_pf = ChoosePixelFormat(dmy_pdc, &dmy_pfd);
       
   661         SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd);
       
   662         dmy_rc = wglCreateContext(dmy_pdc);
       
   663         old_dc = wglGetCurrentDC();
       
   664         old_context = wglGetCurrentContext();
       
   665         wglMakeCurrent(dmy_pdc, dmy_rc);
       
   666     }
       
   667 
       
   668     ~QGLTempContext() {
       
   669         wglMakeCurrent(dmy_pdc, 0);
       
   670         wglDeleteContext(dmy_rc);
       
   671         ReleaseDC(dmy_id, dmy_pdc);
       
   672         DestroyWindow(dmy_id);
       
   673         if (old_dc && old_context)
       
   674             wglMakeCurrent(old_dc, old_context);
       
   675     }
       
   676 
       
   677     HDC dmy_pdc;
       
   678     HGLRC dmy_rc;
       
   679     HDC old_dc;
       
   680     HGLRC old_context;
       
   681     WId dmy_id;
       
   682 };
       
   683 
       
   684 bool QGLContext::chooseContext(const QGLContext* shareContext)
       
   685 {
       
   686     Q_D(QGLContext);
       
   687     // workaround for matrox driver:
       
   688     // make a cheap call to opengl to force loading of DLL
       
   689     if (!opengl32dll) {
       
   690         GLint params;
       
   691         glGetIntegerv(GL_DEPTH_BITS, &params);
       
   692         opengl32dll = true;
       
   693     }
       
   694 
       
   695     bool result = true;
       
   696     HDC myDc;
       
   697     QWidget *widget = 0;
       
   698 
       
   699     if (deviceIsPixmap()) {
       
   700         if (d->glFormat.plane())
       
   701             return false;                // Pixmaps can't have overlay
       
   702         d->win = 0;
       
   703         HDC display_dc = GetDC(0);
       
   704         myDc = d->hbitmap_hdc = CreateCompatibleDC(display_dc);
       
   705         QPixmap *px = static_cast<QPixmap *>(d->paintDevice);
       
   706 
       
   707         BITMAPINFO bmi;
       
   708         memset(&bmi, 0, sizeof(bmi));
       
   709         bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
       
   710         bmi.bmiHeader.biWidth       = px->width();
       
   711         bmi.bmiHeader.biHeight      = px->height();
       
   712         bmi.bmiHeader.biPlanes      = 1;
       
   713         bmi.bmiHeader.biBitCount    = 32;
       
   714         bmi.bmiHeader.biCompression = BI_RGB;
       
   715         d->hbitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, 0, 0, 0);
       
   716         SelectObject(myDc, d->hbitmap);
       
   717         ReleaseDC(0, display_dc);
       
   718     } else {
       
   719         widget = static_cast<QWidget *>(d->paintDevice);
       
   720         d->win = widget->winId();
       
   721         myDc = GetDC(d->win);
       
   722     }
       
   723 
       
   724     // NB! the QGLTempContext object is needed for the
       
   725     // wglGetProcAddress() calls to succeed and are absolutely
       
   726     // necessary - don't remove!
       
   727     QGLTempContext tmp_ctx(d->glFormat.directRendering(), widget);
       
   728 
       
   729     if (!myDc) {
       
   730         qWarning("QGLContext::chooseContext(): Paint device cannot be null");
       
   731         result = false;
       
   732         goto end;
       
   733     }
       
   734 
       
   735     if (d->glFormat.plane()) {
       
   736         d->pixelFormatId = ((QGLWidget*)d->paintDevice)->context()->d_func()->pixelFormatId;
       
   737         if (!d->pixelFormatId) {                // I.e. the glwidget is invalid
       
   738             qWarning("QGLContext::chooseContext(): Cannot create overlay context for invalid widget");
       
   739             result = false;
       
   740             goto end;
       
   741         }
       
   742 
       
   743         d->rc = wglCreateLayerContext(myDc, d->glFormat.plane());
       
   744         if (!d->rc) {
       
   745             qwglError("QGLContext::chooseContext()", "CreateLayerContext");
       
   746             result = false;
       
   747             goto end;
       
   748         }
       
   749 
       
   750         LAYERPLANEDESCRIPTOR lpfd;
       
   751         wglDescribeLayerPlane(myDc, d->pixelFormatId, d->glFormat.plane(), sizeof(LAYERPLANEDESCRIPTOR), &lpfd);
       
   752         d->glFormat.setDoubleBuffer(lpfd.dwFlags & LPD_DOUBLEBUFFER);
       
   753         d->glFormat.setDepth(lpfd.cDepthBits);
       
   754         d->glFormat.setRgba(lpfd.iPixelType == PFD_TYPE_RGBA);
       
   755         if (d->glFormat.rgba()) {
       
   756             if (d->glFormat.redBufferSize() != -1)
       
   757                 d->glFormat.setRedBufferSize(lpfd.cRedBits);
       
   758             if (d->glFormat.greenBufferSize() != -1)
       
   759                 d->glFormat.setGreenBufferSize(lpfd.cGreenBits);
       
   760             if (d->glFormat.blueBufferSize() != -1)
       
   761                 d->glFormat.setBlueBufferSize(lpfd.cBlueBits);
       
   762         }
       
   763         d->glFormat.setAlpha(lpfd.cAlphaBits);
       
   764         d->glFormat.setAccum(lpfd.cAccumBits);
       
   765         d->glFormat.setStencil(lpfd.cStencilBits);
       
   766         d->glFormat.setStereo(lpfd.dwFlags & LPD_STEREO);
       
   767         d->glFormat.setDirectRendering(false);
       
   768         if (d->glFormat.depth())
       
   769             d->glFormat.setDepthBufferSize(lpfd.cDepthBits);
       
   770         if (d->glFormat.alpha())
       
   771             d->glFormat.setAlphaBufferSize(lpfd.cAlphaBits);
       
   772         if (d->glFormat.accum())
       
   773             d->glFormat.setAccumBufferSize(lpfd.cAccumRedBits);
       
   774         if (d->glFormat.stencil())
       
   775             d->glFormat.setStencilBufferSize(lpfd.cStencilBits);
       
   776 
       
   777         if (d->glFormat.rgba()) {
       
   778             if (lpfd.dwFlags & LPD_TRANSPARENT)
       
   779                 d->transpColor = QColor(lpfd.crTransparent & 0xff,
       
   780                                         (lpfd.crTransparent >> 8) & 0xff,
       
   781                                         (lpfd.crTransparent >> 16) & 0xff);
       
   782             else
       
   783                 d->transpColor = QColor(0, 0, 0);
       
   784         }
       
   785         else {
       
   786             if (lpfd.dwFlags & LPD_TRANSPARENT)
       
   787                 d->transpColor = QColor(qRgb(1, 2, 3));//, lpfd.crTransparent);
       
   788             else
       
   789                 d->transpColor = QColor(qRgb(1, 2, 3));//, 0);
       
   790 
       
   791             d->cmap = new QGLCmap(1 << lpfd.cColorBits);
       
   792             d->cmap->setEntry(lpfd.crTransparent, qRgb(1, 2, 3));//, QGLCmap::Reserved);
       
   793         }
       
   794 
       
   795         if (shareContext && shareContext->isValid()) {
       
   796             QGLContext *share = const_cast<QGLContext *>(shareContext);
       
   797             d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
       
   798             share->d_func()->sharing = d->sharing;
       
   799         }
       
   800 
       
   801         goto end;
       
   802     }
       
   803     {
       
   804         PIXELFORMATDESCRIPTOR pfd;
       
   805         PIXELFORMATDESCRIPTOR realPfd;
       
   806         d->pixelFormatId = choosePixelFormat(&pfd, myDc);
       
   807         if (d->pixelFormatId == 0) {
       
   808             qwglError("QGLContext::chooseContext()", "ChoosePixelFormat");
       
   809             result = false;
       
   810             goto end;
       
   811         }
       
   812 
       
   813         bool overlayRequested = d->glFormat.hasOverlay();
       
   814         DescribePixelFormat(myDc, d->pixelFormatId, sizeof(PIXELFORMATDESCRIPTOR), &realPfd);
       
   815 
       
   816         if (!deviceIsPixmap() && wglGetProcAddress("wglGetPixelFormatAttribivARB"))
       
   817             d->glFormat = pfiToQGLFormat(myDc, d->pixelFormatId);
       
   818         else
       
   819             d->glFormat = pfdToQGLFormat(&realPfd);
       
   820 
       
   821         d->glFormat.setOverlay(d->glFormat.hasOverlay() && overlayRequested);
       
   822 
       
   823         if (deviceIsPixmap() && !(realPfd.dwFlags & PFD_DRAW_TO_BITMAP)) {
       
   824             qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context.");
       
   825             result = false;
       
   826             goto end;
       
   827         }
       
   828 
       
   829         if (deviceIsPixmap() &&
       
   830             (((QPixmap*)d->paintDevice)->depth() != realPfd.cColorBits)) {
       
   831             qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context of suitable depth.");
       
   832             result = false;
       
   833             goto end;
       
   834         }
       
   835 
       
   836         if (!SetPixelFormat(myDc, d->pixelFormatId, &realPfd)) {
       
   837             qwglError("QGLContext::chooseContext()", "SetPixelFormat");
       
   838             result = false;
       
   839             goto end;
       
   840         }
       
   841 
       
   842         if (!(d->rc = wglCreateLayerContext(myDc, 0))) {
       
   843             qwglError("QGLContext::chooseContext()", "wglCreateContext");
       
   844             result = false;
       
   845             goto end;
       
   846         }
       
   847 
       
   848         if (shareContext && shareContext->isValid()) {
       
   849             d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
       
   850             const_cast<QGLContext *>(shareContext)->d_func()->sharing = d->sharing;
       
   851         }
       
   852 
       
   853         if(!deviceIsPixmap()) {
       
   854             QRgb* pal = qgl_create_rgb_palette(&realPfd);
       
   855             if (pal) {
       
   856                 QGLColormap cmap;
       
   857                 cmap.setEntries(256, pal);
       
   858                 ((QGLWidget*)d->paintDevice)->setColormap(cmap);
       
   859                 delete[] pal;
       
   860             }
       
   861         }
       
   862     }
       
   863 
       
   864 end:
       
   865     // vblanking
       
   866     wglMakeCurrent(myDc, d->rc);
       
   867     typedef BOOL (APIENTRYP PFNWGLSWAPINTERVALEXT) (int interval);
       
   868     typedef int (APIENTRYP PFNWGLGETSWAPINTERVALEXT) (void);
       
   869     PFNWGLSWAPINTERVALEXT wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXT) wglGetProcAddress("wglSwapIntervalEXT");
       
   870     PFNWGLGETSWAPINTERVALEXT wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXT) wglGetProcAddress("wglGetSwapIntervalEXT");
       
   871     if (wglSwapIntervalEXT && wglGetSwapIntervalEXT) {
       
   872         if (d->reqFormat.swapInterval() != -1)
       
   873             wglSwapIntervalEXT(d->reqFormat.swapInterval());
       
   874         d->glFormat.setSwapInterval(wglGetSwapIntervalEXT());
       
   875     }
       
   876 
       
   877     if (d->win)
       
   878         ReleaseDC(d->win, myDc);
       
   879     return result;
       
   880 }
       
   881 
       
   882 
       
   883 
       
   884 static bool qLogEq(bool a, bool b)
       
   885 {
       
   886     return (((!a) && (!b)) || (a && b));
       
   887 }
       
   888 
       
   889 /*
       
   890   See qgl.cpp for qdoc comment.
       
   891  */
       
   892 int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
       
   893 {
       
   894     Q_D(QGLContext);
       
   895     // workaround for matrox driver:
       
   896     // make a cheap call to opengl to force loading of DLL
       
   897     if (!opengl32dll) {
       
   898         GLint params;
       
   899         glGetIntegerv(GL_DEPTH_BITS, &params);
       
   900         opengl32dll = true;
       
   901     }
       
   902 
       
   903     PFNWGLCHOOSEPIXELFORMATARB wglChoosePixelFormatARB =
       
   904         (PFNWGLCHOOSEPIXELFORMATARB) wglGetProcAddress("wglChoosePixelFormatARB");
       
   905     int chosenPfi = 0;
       
   906     if (!deviceIsPixmap() && wglChoosePixelFormatARB) {
       
   907         bool valid;
       
   908         int pixelFormat = 0;
       
   909         uint numFormats = 0;
       
   910         QVarLengthArray<int> iAttributes(40);
       
   911         int i = 0;
       
   912         iAttributes[i++] = WGL_ACCELERATION_ARB;
       
   913         if (d->glFormat.directRendering())
       
   914             iAttributes[i++] = WGL_FULL_ACCELERATION_ARB;
       
   915         else
       
   916             iAttributes[i++] = WGL_NO_ACCELERATION_ARB;
       
   917         iAttributes[i++] = WGL_SUPPORT_OPENGL_ARB;
       
   918         iAttributes[i++] = TRUE;
       
   919         iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB;
       
   920         iAttributes[i++] = TRUE;
       
   921         iAttributes[i++] = WGL_COLOR_BITS_ARB;
       
   922         iAttributes[i++] = 32;
       
   923         iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
       
   924         iAttributes[i++] = d->glFormat.doubleBuffer();
       
   925         if (d->glFormat.stereo()) {
       
   926             iAttributes[i++] = WGL_STEREO_ARB;
       
   927             iAttributes[i++] = TRUE;
       
   928         }
       
   929         if (d->glFormat.depth()) {
       
   930             iAttributes[i++] = WGL_DEPTH_BITS_ARB;
       
   931             iAttributes[i++] = d->glFormat.depthBufferSize() == -1 ? 24 : d->glFormat.depthBufferSize();
       
   932         }
       
   933         iAttributes[i++] = WGL_PIXEL_TYPE_ARB;
       
   934         if (d->glFormat.rgba()) {
       
   935             iAttributes[i++] = WGL_TYPE_RGBA_ARB;
       
   936             if (d->glFormat.redBufferSize() != -1) {
       
   937                 iAttributes[i++] = WGL_RED_BITS_ARB;
       
   938                 iAttributes[i++] = d->glFormat.redBufferSize();
       
   939             }
       
   940             if (d->glFormat.greenBufferSize() != -1) {
       
   941                 iAttributes[i++] = WGL_GREEN_BITS_ARB;
       
   942                 iAttributes[i++] = d->glFormat.greenBufferSize();
       
   943             }
       
   944             if (d->glFormat.blueBufferSize() != -1) {
       
   945                 iAttributes[i++] = WGL_BLUE_BITS_ARB;
       
   946                 iAttributes[i++] = d->glFormat.blueBufferSize();
       
   947             }
       
   948         } else {
       
   949             iAttributes[i++] = WGL_TYPE_COLORINDEX_ARB;
       
   950         }
       
   951         if (d->glFormat.alpha()) {
       
   952             iAttributes[i++] = WGL_ALPHA_BITS_ARB;
       
   953             iAttributes[i++] = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize();
       
   954         }
       
   955         if (d->glFormat.accum()) {
       
   956             iAttributes[i++] = WGL_ACCUM_BITS_ARB;
       
   957             iAttributes[i++] = d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize();
       
   958         }
       
   959         if (d->glFormat.stencil()) {
       
   960             iAttributes[i++] = WGL_STENCIL_BITS_ARB;
       
   961             iAttributes[i++] = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize();
       
   962         }
       
   963         if (d->glFormat.hasOverlay()) {
       
   964             iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB;
       
   965             iAttributes[i++] = 1;
       
   966         }
       
   967         int si = 0;
       
   968         bool trySampleBuffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
       
   969         if (trySampleBuffers && d->glFormat.sampleBuffers()) {
       
   970             iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
       
   971             iAttributes[i++] = TRUE;
       
   972             iAttributes[i++] = WGL_SAMPLES_ARB;
       
   973             si = i;
       
   974             iAttributes[i++] = d->glFormat.samples() == -1 ? 4 : d->glFormat.samples();
       
   975         }
       
   976         iAttributes[i] = 0;
       
   977 
       
   978         do {
       
   979             valid = wglChoosePixelFormatARB(pdc, iAttributes.constData(), 0, 1,
       
   980                                             &pixelFormat, &numFormats);
       
   981             if (trySampleBuffers  && (!valid || numFormats < 1) && d->glFormat.sampleBuffers())
       
   982                 iAttributes[si] /= 2; // try different no. samples - we aim for the best one
       
   983             else
       
   984                 break;
       
   985         } while ((!valid || numFormats < 1) && iAttributes[si] > 1);
       
   986         chosenPfi = pixelFormat;
       
   987     }
       
   988 
       
   989     if (!chosenPfi) { // fallback if wglChoosePixelFormatARB() failed
       
   990         int pmDepth = deviceIsPixmap() ? ((QPixmap*)d->paintDevice)->depth() : 0;
       
   991         PIXELFORMATDESCRIPTOR* p = (PIXELFORMATDESCRIPTOR*)dummyPfd;
       
   992         memset(p, 0, sizeof(PIXELFORMATDESCRIPTOR));
       
   993         p->nSize = sizeof(PIXELFORMATDESCRIPTOR);
       
   994         p->nVersion = 1;
       
   995         p->dwFlags  = PFD_SUPPORT_OPENGL;
       
   996         if (deviceIsPixmap())
       
   997             p->dwFlags |= PFD_DRAW_TO_BITMAP;
       
   998         else
       
   999             p->dwFlags |= PFD_DRAW_TO_WINDOW;
       
  1000         if (!d->glFormat.directRendering())
       
  1001             p->dwFlags |= PFD_GENERIC_FORMAT;
       
  1002         if (d->glFormat.doubleBuffer() && !deviceIsPixmap())
       
  1003             p->dwFlags |= PFD_DOUBLEBUFFER;
       
  1004         if (d->glFormat.stereo())
       
  1005             p->dwFlags |= PFD_STEREO;
       
  1006         if (d->glFormat.depth())
       
  1007             p->cDepthBits = d->glFormat.depthBufferSize() == -1 ? 32 : d->glFormat.depthBufferSize();
       
  1008         else
       
  1009             p->dwFlags |= PFD_DEPTH_DONTCARE;
       
  1010         if (d->glFormat.rgba()) {
       
  1011             p->iPixelType = PFD_TYPE_RGBA;
       
  1012             if (d->glFormat.redBufferSize() != -1)
       
  1013                 p->cRedBits = d->glFormat.redBufferSize();
       
  1014             if (d->glFormat.greenBufferSize() != -1)
       
  1015                 p->cGreenBits = d->glFormat.greenBufferSize();
       
  1016             if (d->glFormat.blueBufferSize() != -1)
       
  1017                 p->cBlueBits = d->glFormat.blueBufferSize();
       
  1018             if (deviceIsPixmap())
       
  1019                 p->cColorBits = pmDepth;
       
  1020             else
       
  1021                 p->cColorBits = 32;
       
  1022         } else {
       
  1023             p->iPixelType = PFD_TYPE_COLORINDEX;
       
  1024             p->cColorBits = 8;
       
  1025         }
       
  1026         if (d->glFormat.alpha())
       
  1027             p->cAlphaBits = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize();
       
  1028         if (d->glFormat.accum()) {
       
  1029             p->cAccumRedBits = p->cAccumGreenBits = p->cAccumBlueBits = p->cAccumAlphaBits =
       
  1030                                d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize();
       
  1031         }
       
  1032         if (d->glFormat.stencil())
       
  1033             p->cStencilBits = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize();
       
  1034         p->iLayerType = PFD_MAIN_PLANE;
       
  1035         chosenPfi = ChoosePixelFormat(pdc, p);
       
  1036 
       
  1037         if (!chosenPfi)
       
  1038             qErrnoWarning("QGLContext: ChoosePixelFormat failed");
       
  1039 
       
  1040         // Since the GDI function ChoosePixelFormat() does not handle
       
  1041         // overlay and direct-rendering requests, we must roll our own here
       
  1042 
       
  1043         bool doSearch = chosenPfi <= 0;
       
  1044         PIXELFORMATDESCRIPTOR pfd;
       
  1045         QGLFormat fmt;
       
  1046         if (!doSearch) {
       
  1047             DescribePixelFormat(pdc, chosenPfi, sizeof(PIXELFORMATDESCRIPTOR),
       
  1048                                 &pfd);
       
  1049             fmt = pfdToQGLFormat(&pfd);
       
  1050             if (d->glFormat.hasOverlay() && !fmt.hasOverlay())
       
  1051                 doSearch = true;
       
  1052             else if (!qLogEq(d->glFormat.directRendering(), fmt.directRendering()))
       
  1053                 doSearch = true;
       
  1054             else if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) ||
       
  1055                                           pfd.cColorBits != pmDepth))
       
  1056                 doSearch = true;
       
  1057             else if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))
       
  1058                 doSearch = true;
       
  1059             else if (!qLogEq(d->glFormat.rgba(), fmt.rgba()))
       
  1060                 doSearch = true;
       
  1061         }
       
  1062 
       
  1063         if (doSearch) {
       
  1064             int pfiMax = DescribePixelFormat(pdc, 0, 0, NULL);
       
  1065             int bestScore = -1;
       
  1066             int bestPfi = -1;
       
  1067             for (int pfi = 1; pfi <= pfiMax; pfi++) {
       
  1068                 DescribePixelFormat(pdc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
       
  1069                 if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
       
  1070                     continue;
       
  1071                 if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) ||
       
  1072                                          pfd.cColorBits != pmDepth))
       
  1073                     continue;
       
  1074                 if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))
       
  1075                     continue;
       
  1076 
       
  1077                 fmt = pfdToQGLFormat(&pfd);
       
  1078                 if (d->glFormat.hasOverlay() && !fmt.hasOverlay())
       
  1079                     continue;
       
  1080 
       
  1081                 int score = pfd.cColorBits;
       
  1082                 if (qLogEq(d->glFormat.depth(), fmt.depth()))
       
  1083                     score += pfd.cDepthBits;
       
  1084                 if (qLogEq(d->glFormat.alpha(), fmt.alpha()))
       
  1085                     score += pfd.cAlphaBits;
       
  1086                 if (qLogEq(d->glFormat.accum(), fmt.accum()))
       
  1087                     score += pfd.cAccumBits;
       
  1088                 if (qLogEq(d->glFormat.stencil(), fmt.stencil()))
       
  1089                     score += pfd.cStencilBits;
       
  1090                 if (qLogEq(d->glFormat.doubleBuffer(), fmt.doubleBuffer()))
       
  1091                     score += 1000;
       
  1092                 if (qLogEq(d->glFormat.stereo(), fmt.stereo()))
       
  1093                     score += 2000;
       
  1094                 if (qLogEq(d->glFormat.directRendering(), fmt.directRendering()))
       
  1095                     score += 4000;
       
  1096                 if (qLogEq(d->glFormat.rgba(), fmt.rgba()))
       
  1097                     score += 8000;
       
  1098                 if (score > bestScore) {
       
  1099                     bestScore = score;
       
  1100                     bestPfi = pfi;
       
  1101                 }
       
  1102             }
       
  1103 
       
  1104             if (bestPfi > 0)
       
  1105                 chosenPfi = bestPfi;
       
  1106         }
       
  1107     }
       
  1108     return chosenPfi;
       
  1109 }
       
  1110 
       
  1111 
       
  1112 
       
  1113 void QGLContext::reset()
       
  1114 {
       
  1115     Q_D(QGLContext);
       
  1116     // workaround for matrox driver:
       
  1117     // make a cheap call to opengl to force loading of DLL
       
  1118     if (!opengl32dll) {
       
  1119         GLint params;
       
  1120         glGetIntegerv(GL_DEPTH_BITS, &params);
       
  1121         opengl32dll = true;
       
  1122     }
       
  1123 
       
  1124     if (!d->valid)
       
  1125         return;
       
  1126     d->cleanup();
       
  1127     doneCurrent();
       
  1128     if (d->rc)
       
  1129         wglDeleteContext(d->rc);
       
  1130     d->rc  = 0;
       
  1131     if (d->win && d->dc)
       
  1132         ReleaseDC(d->win, d->dc);
       
  1133     if (deviceIsPixmap()) {
       
  1134         DeleteDC(d->hbitmap_hdc);
       
  1135         DeleteObject(d->hbitmap);
       
  1136         d->hbitmap_hdc = 0;
       
  1137         d->hbitmap = 0;
       
  1138     }
       
  1139     d->dc  = 0;
       
  1140     d->win = 0;
       
  1141     d->pixelFormatId = 0;
       
  1142     d->sharing = false;
       
  1143     d->valid = false;
       
  1144     d->transpColor = QColor();
       
  1145     delete d->cmap;
       
  1146     d->cmap = 0;
       
  1147     d->initDone = false;
       
  1148     qgl_share_reg()->removeShare(this);
       
  1149 }
       
  1150 
       
  1151 //
       
  1152 // NOTE: In a multi-threaded environment, each thread has a current
       
  1153 // context. If we want to make this code thread-safe, we probably
       
  1154 // have to use TLS (thread local storage) for keeping current contexts.
       
  1155 //
       
  1156 
       
  1157 void QGLContext::makeCurrent()
       
  1158 {
       
  1159     Q_D(QGLContext);
       
  1160     if (d->rc == wglGetCurrentContext() || !d->valid)        // already current
       
  1161         return;
       
  1162     if (d->win) {
       
  1163         d->dc = GetDC(d->win);
       
  1164         if (!d->dc) {
       
  1165             qwglError("QGLContext::makeCurrent()", "GetDC()");
       
  1166             return;
       
  1167         }
       
  1168     } else if (deviceIsPixmap()) {
       
  1169         d->dc = d->hbitmap_hdc;
       
  1170     }
       
  1171 
       
  1172     HPALETTE hpal = QColormap::hPal();
       
  1173     if (hpal) {
       
  1174         SelectPalette(d->dc, hpal, FALSE);
       
  1175         RealizePalette(d->dc);
       
  1176     }
       
  1177     if (d->glFormat.plane()) {
       
  1178         wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE);
       
  1179     }
       
  1180 
       
  1181     if (wglMakeCurrent(d->dc, d->rc)) {
       
  1182         QGLContextPrivate::setCurrentContext(this);
       
  1183     } else {
       
  1184         qwglError("QGLContext::makeCurrent()", "wglMakeCurrent");
       
  1185     }
       
  1186 }
       
  1187 
       
  1188 
       
  1189 void QGLContext::doneCurrent()
       
  1190 {
       
  1191     Q_D(QGLContext);
       
  1192     wglMakeCurrent(0, 0);
       
  1193     QGLContextPrivate::setCurrentContext(0);
       
  1194     if (deviceIsPixmap() && d->hbitmap) {
       
  1195         QPixmap *pm = static_cast<QPixmap *>(d->paintDevice);
       
  1196         *pm = QPixmap::fromWinHBITMAP(d->hbitmap);
       
  1197     }
       
  1198     if (d->win && d->dc) {
       
  1199         ReleaseDC(d->win, d->dc);
       
  1200         d->dc = 0;
       
  1201     }
       
  1202 }
       
  1203 
       
  1204 void QGLContext::swapBuffers() const
       
  1205 {
       
  1206     Q_D(const QGLContext);
       
  1207     if (d->dc && d->glFormat.doubleBuffer() && !deviceIsPixmap()) {
       
  1208         if (d->glFormat.plane())
       
  1209             wglSwapLayerBuffers(d->dc, WGL_SWAP_OVERLAY1);
       
  1210         else {
       
  1211             if (d->glFormat.hasOverlay())
       
  1212                 wglSwapLayerBuffers(d->dc, WGL_SWAP_MAIN_PLANE);
       
  1213             else
       
  1214                 SwapBuffers(d->dc);
       
  1215         }
       
  1216     }
       
  1217 }
       
  1218 
       
  1219 
       
  1220 QColor QGLContext::overlayTransparentColor() const
       
  1221 {
       
  1222     return d_func()->transpColor;
       
  1223 }
       
  1224 
       
  1225 
       
  1226 uint QGLContext::colorIndex(const QColor& c) const
       
  1227 {
       
  1228     Q_D(const QGLContext);
       
  1229     if (!isValid())
       
  1230         return 0;
       
  1231     if (d->cmap) {
       
  1232         int idx = d->cmap->find(c.rgb());
       
  1233         if (idx >= 0)
       
  1234             return idx;
       
  1235         if (d->dc && d->glFormat.plane()) {
       
  1236             idx = d->cmap->allocate(c.rgb());
       
  1237             if (idx >= 0) {
       
  1238                 COLORREF r = RGB(qRed(c.rgb()),qGreen(c.rgb()),qBlue(c.rgb()));
       
  1239                 wglSetLayerPaletteEntries(d->dc, d->glFormat.plane(), idx, 1, &r);
       
  1240                 wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE);
       
  1241                 return idx;
       
  1242             }
       
  1243         }
       
  1244         return d->cmap->findNearest(c.rgb());
       
  1245     }
       
  1246     QColormap cmap = QColormap::instance();
       
  1247     return cmap.pixel(c) & 0x00ffffff; // Assumes standard palette
       
  1248 }
       
  1249 
       
  1250 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
       
  1251 {
       
  1252     if (!isValid())
       
  1253         return;
       
  1254 
       
  1255     HDC display_dc = GetDC(0);
       
  1256     HDC tmp_dc = CreateCompatibleDC(display_dc);
       
  1257     HGDIOBJ old_font = SelectObject(tmp_dc, fnt.handle());
       
  1258 
       
  1259     ReleaseDC(0, display_dc);
       
  1260 
       
  1261     if (!wglUseFontBitmaps(tmp_dc, 0, 256, listBase))
       
  1262         qWarning("QGLContext::generateFontDisplayLists: Could not generate display lists for font '%s'", fnt.family().toLatin1().data());
       
  1263 
       
  1264     SelectObject(tmp_dc, old_font);
       
  1265     DeleteDC(tmp_dc);
       
  1266 }
       
  1267 
       
  1268 void *QGLContext::getProcAddress(const QString &proc) const
       
  1269 {
       
  1270     return (void *)wglGetProcAddress(proc.toLatin1());
       
  1271 }
       
  1272 
       
  1273 /*****************************************************************************
       
  1274   QGLWidget Win32/WGL-specific code
       
  1275  *****************************************************************************/
       
  1276 
       
  1277 void QGLWidgetPrivate::init(QGLContext *ctx, const QGLWidget* shareWidget)
       
  1278 {
       
  1279     Q_Q(QGLWidget);
       
  1280     olcx = 0;
       
  1281     initContext(ctx, shareWidget);
       
  1282 
       
  1283     if (q->isValid() && q->context()->format().hasOverlay()) {
       
  1284         olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), q);
       
  1285         if (!olcx->create(shareWidget ? shareWidget->overlayContext() : 0)) {
       
  1286             delete olcx;
       
  1287             olcx = 0;
       
  1288             glcx->d_func()->glFormat.setOverlay(false);
       
  1289         }
       
  1290     } else {
       
  1291         olcx = 0;
       
  1292     }
       
  1293 }
       
  1294 
       
  1295 /*\internal
       
  1296   Store color values in the given colormap.
       
  1297 */
       
  1298 static void qStoreColors(HPALETTE cmap, const QGLColormap & cols)
       
  1299 {
       
  1300     QRgb color;
       
  1301     PALETTEENTRY pe;
       
  1302 
       
  1303     for (int i = 0; i < cols.size(); i++) {
       
  1304         color = cols.entryRgb(i);
       
  1305         pe.peRed   = qRed(color);
       
  1306         pe.peGreen = qGreen(color);
       
  1307         pe.peBlue  = qBlue(color);
       
  1308         pe.peFlags = 0;
       
  1309 
       
  1310         SetPaletteEntries(cmap, i, 1, &pe);
       
  1311     }
       
  1312 }
       
  1313 
       
  1314 void QGLWidgetPrivate::updateColormap()
       
  1315 {
       
  1316     Q_Q(QGLWidget);
       
  1317     if (!cmap.handle())
       
  1318         return;
       
  1319     HDC hdc = GetDC(q->winId());
       
  1320     SelectPalette(hdc, (HPALETTE) cmap.handle(), TRUE);
       
  1321     qStoreColors((HPALETTE) cmap.handle(), cmap);
       
  1322     RealizePalette(hdc);
       
  1323     ReleaseDC(q->winId(), hdc);
       
  1324 }
       
  1325 
       
  1326 void QGLWidget::setMouseTracking(bool enable)
       
  1327 {
       
  1328     QWidget::setMouseTracking(enable);
       
  1329 }
       
  1330 
       
  1331 
       
  1332 void QGLWidget::resizeEvent(QResizeEvent *)
       
  1333 {
       
  1334     Q_D(QGLWidget);
       
  1335     if (!isValid())
       
  1336         return;
       
  1337     makeCurrent();
       
  1338     if (!d->glcx->initialized())
       
  1339         glInit();
       
  1340     resizeGL(width(), height());
       
  1341     if (d->olcx) {
       
  1342         makeOverlayCurrent();
       
  1343         resizeOverlayGL(width(), height());
       
  1344     }
       
  1345 }
       
  1346 
       
  1347 
       
  1348 const QGLContext* QGLWidget::overlayContext() const
       
  1349 {
       
  1350     return d_func()->olcx;
       
  1351 }
       
  1352 
       
  1353 
       
  1354 void QGLWidget::makeOverlayCurrent()
       
  1355 {
       
  1356     Q_D(QGLWidget);
       
  1357     if (d->olcx) {
       
  1358         d->olcx->makeCurrent();
       
  1359         if (!d->olcx->initialized()) {
       
  1360             initializeOverlayGL();
       
  1361             d->olcx->setInitialized(true);
       
  1362         }
       
  1363     }
       
  1364 }
       
  1365 
       
  1366 
       
  1367 void QGLWidget::updateOverlayGL()
       
  1368 {
       
  1369     Q_D(QGLWidget);
       
  1370     if (d->olcx) {
       
  1371         makeOverlayCurrent();
       
  1372         paintOverlayGL();
       
  1373         if (d->olcx->format().doubleBuffer()) {
       
  1374             if (d->autoSwap)
       
  1375                 d->olcx->swapBuffers();
       
  1376         }
       
  1377         else {
       
  1378             glFlush();
       
  1379         }
       
  1380     }
       
  1381 }
       
  1382 
       
  1383 
       
  1384 void QGLWidget::setContext(QGLContext *context,
       
  1385                             const QGLContext* shareContext,
       
  1386                             bool deleteOldContext)
       
  1387 {
       
  1388     Q_D(QGLWidget);
       
  1389     if (context == 0) {
       
  1390         qWarning("QGLWidget::setContext: Cannot set null context");
       
  1391         return;
       
  1392     }
       
  1393     if (!context->deviceIsPixmap() && context->device() != this) {
       
  1394         qWarning("QGLWidget::setContext: Context must refer to this widget");
       
  1395         return;
       
  1396     }
       
  1397 
       
  1398     if (d->glcx)
       
  1399         d->glcx->doneCurrent();
       
  1400     QGLContext* oldcx = d->glcx;
       
  1401     d->glcx = context;
       
  1402 
       
  1403     bool doShow = false;
       
  1404     if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) {
       
  1405         // We already have a context and must therefore create a new
       
  1406         // window since Windows does not permit setting a new OpenGL
       
  1407         // context for a window that already has one set.
       
  1408         doShow = isVisible();
       
  1409         QWidget *pW = static_cast<QWidget *>(parent());
       
  1410         QPoint pos = geometry().topLeft();
       
  1411         setParent(pW, windowFlags());
       
  1412         move(pos);
       
  1413     }
       
  1414 
       
  1415     if (!d->glcx->isValid()) {
       
  1416         bool wasSharing = shareContext || (oldcx && oldcx->isSharing());
       
  1417         d->glcx->create(shareContext ? shareContext : oldcx);
       
  1418         // the above is a trick to keep disp lists etc when a
       
  1419         // QGLWidget has been reparented, so remove the sharing
       
  1420         // flag if we don't actually have a sharing context.
       
  1421         if (!wasSharing)
       
  1422             d->glcx->d_ptr->sharing = false;
       
  1423     }
       
  1424 
       
  1425     if (deleteOldContext)
       
  1426         delete oldcx;
       
  1427 
       
  1428     if (doShow)
       
  1429         show();
       
  1430 }
       
  1431 
       
  1432 
       
  1433 bool QGLWidgetPrivate::renderCxPm(QPixmap*)
       
  1434 {
       
  1435     return false;
       
  1436 }
       
  1437 
       
  1438 void QGLWidgetPrivate::cleanupColormaps()
       
  1439 {
       
  1440     Q_Q(QGLWidget);
       
  1441     if (cmap.handle()) {
       
  1442         HDC hdc = GetDC(q->winId());
       
  1443         SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), FALSE);
       
  1444         DeleteObject((HPALETTE) cmap.handle());
       
  1445         ReleaseDC(q->winId(), hdc);
       
  1446         cmap.setHandle(0);
       
  1447     }
       
  1448     return;
       
  1449 }
       
  1450 
       
  1451 const QGLColormap & QGLWidget::colormap() const
       
  1452 {
       
  1453     return d_func()->cmap;
       
  1454 }
       
  1455 
       
  1456 void QGLWidget::setColormap(const QGLColormap & c)
       
  1457 {
       
  1458     Q_D(QGLWidget);
       
  1459     d->cmap = c;
       
  1460 
       
  1461     if (d->cmap.handle()) { // already have an allocated cmap
       
  1462         d->updateColormap();
       
  1463     } else {
       
  1464         LOGPALETTE *lpal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE)
       
  1465                                                  +c.size()*sizeof(PALETTEENTRY));
       
  1466         lpal->palVersion    = 0x300;
       
  1467         lpal->palNumEntries = c.size();
       
  1468         d->cmap.setHandle(CreatePalette(lpal));
       
  1469         free(lpal);
       
  1470         d->updateColormap();
       
  1471     }
       
  1472 }
       
  1473 
       
  1474 void QGLExtensions::init()
       
  1475 {
       
  1476     static bool init_done = false;
       
  1477 
       
  1478     if (init_done)
       
  1479         return;
       
  1480     init_done = true;
       
  1481     QGLTempContext temp_ctx(QGLFormat::defaultFormat().directRendering());
       
  1482     init_extensions();
       
  1483 }
       
  1484 
       
  1485 QT_END_NAMESPACE