Re-apply change 353dcfd307853da289fdd245410e2e07358624a0 by Friedemann Kleint
[qt-netbsd.git] / src / opengl / qgl_win.cpp
blob40b0ce7ae37f60a78392780ecfd00902d4e75cbc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 **
6 ** This file is part of the QtOpenGL module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** No Commercial Usage
10 ** This file contains pre-release code and may not be distributed.
11 ** You may use this file in accordance with the terms and conditions
12 ** contained in the either Technology Preview License Agreement or the
13 ** Beta Release License Agreement.
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 ** In addition, as a special exception, Nokia gives you certain
24 ** additional rights. These rights are described in the Nokia Qt LGPL
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26 ** package.
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 3.0 as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL included in the
32 ** packaging of this file. Please review the following information to
33 ** ensure the GNU General Public License version 3.0 requirements will be
34 ** met: http://www.gnu.org/copyleft/gpl.html.
36 ** If you are unsure which license is appropriate for your use, please
37 ** contact the sales department at http://www.qtsoftware.com/contact.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
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>
54 #include <windows.h>
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
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
125 QT_BEGIN_NAMESPACE
127 class QGLCmapPrivate
129 public:
130 QGLCmapPrivate() : count(1) { }
131 void ref() { ++count; }
132 bool deref() { return !--count; }
133 uint count;
135 enum AllocState{ UnAllocated = 0, Allocated = 0x01, Reserved = 0x02 };
137 int maxSize;
138 QVector<uint> colorArray;
139 QVector<quint8> allocArray;
140 QVector<quint8> contextArray;
141 QMap<uint,int> colorMap;
144 /*****************************************************************************
145 QColorMap class - temporarily here, until it is ready for prime time
146 *****************************************************************************/
148 /****************************************************************************
150 ** Definition of QColorMap class
152 ****************************************************************************/
154 class QGLCmapPrivate;
156 class /*Q_EXPORT*/ QGLCmap
158 public:
159 enum Flags { Reserved = 0x01 };
161 QGLCmap(int maxSize = 256);
162 QGLCmap(const QGLCmap& map);
163 ~QGLCmap();
165 QGLCmap& operator=(const QGLCmap& map);
167 // isEmpty and/or isNull ?
168 int size() const;
169 int maxSize() const;
171 void resize(int newSize);
173 int find(QRgb color) const;
174 int findNearest(QRgb color) const;
175 int allocate(QRgb color, uint flags = 0, quint8 context = 0);
177 void setEntry(int idx, QRgb color, uint flags = 0, quint8 context = 0);
179 const QRgb* colors() const;
181 private:
182 void detach();
183 QGLCmapPrivate* d;
187 QGLCmap::QGLCmap(int maxSize) // add a bool prealloc?
189 d = new QGLCmapPrivate;
190 d->maxSize = maxSize;
194 QGLCmap::QGLCmap(const QGLCmap& map)
196 d = map.d;
197 d->ref();
201 QGLCmap::~QGLCmap()
203 if (d && d->deref())
204 delete d;
205 d = 0;
209 QGLCmap& QGLCmap::operator=(const QGLCmap& map)
211 map.d->ref();
212 if (d->deref())
213 delete d;
214 d = map.d;
215 return *this;
219 int QGLCmap::size() const
221 return d->colorArray.size();
225 int QGLCmap::maxSize() const
227 return d->maxSize;
231 void QGLCmap::detach()
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;
249 void QGLCmap::resize(int newSize)
251 if (newSize < 0 || newSize > d->maxSize) {
252 qWarning("QGLCmap::resize(): size out of range");
253 return;
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);
268 int QGLCmap::find(QRgb color) const
270 QMap<uint,int>::ConstIterator it = d->colorMap.find(color);
271 if (it != d->colorMap.end())
272 return *it;
273 return -1;
277 int QGLCmap::findNearest(QRgb color) const
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;
301 return idx;
307 // Does not always allocate; returns existing c idx if found
309 int QGLCmap::allocate(QRgb color, uint flags, quint8 context)
311 int idx = find(color);
312 if (idx >= 0)
313 return idx;
315 int mapSize = d->colorArray.size();
316 int newIdx = d->allocArray.indexOf(QGLCmapPrivate::UnAllocated);
318 if (newIdx < 0) { // Must allocate more room
319 if (mapSize < d->maxSize) {
320 newIdx = mapSize;
321 mapSize++;
322 resize(mapSize);
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;
331 d->colorArray[newIdx] = color;
332 if (flags & QGLCmap::Reserved) {
333 d->allocArray[newIdx] = QGLCmapPrivate::Reserved;
335 else {
336 d->allocArray[newIdx] = QGLCmapPrivate::Allocated;
337 d->colorMap.insert(color, newIdx);
339 d->contextArray[newIdx] = context;
340 return newIdx;
344 void QGLCmap::setEntry(int idx, QRgb color, uint flags, quint8 context)
346 if (idx < 0 || idx >= d->maxSize) {
347 qWarning("QGLCmap::set(): Index out of range");
348 return;
350 detach();
351 int mapSize = size();
352 if (idx >= mapSize) {
353 mapSize = idx + 1;
354 resize(mapSize);
356 d->colorArray[idx] = color;
357 if (flags & QGLCmap::Reserved) {
358 d->allocArray[idx] = QGLCmapPrivate::Reserved;
360 else {
361 d->allocArray[idx] = QGLCmapPrivate::Allocated;
362 d->colorMap.insert(color, idx);
364 d->contextArray[idx] = context;
368 const QRgb* QGLCmap::colors() const
370 return d->colorArray.data();
375 /*****************************************************************************
376 QGLFormat Win32/WGL-specific code
377 *****************************************************************************/
380 void qwglError(const char* method, const char* func)
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
399 bool QGLFormat::hasOpenGL()
401 return true;
404 static bool opengl32dll = false;
406 bool QGLFormat::hasOpenGLOverlays()
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;
416 static bool checkDone = false;
417 static bool hasOl = false;
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;
437 ReleaseDC(0, display_dc);
439 return hasOl;
443 /*****************************************************************************
444 QGLContext Win32/WGL-specific code
445 *****************************************************************************/
447 static uchar qgl_rgb_palette_comp(int idx, uint nbits, uint shift)
449 const uchar map_3_to_8[8] = {
450 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
452 const uchar map_2_to_8[4] = {
453 0, 0x55, 0xaa, 0xff
455 const uchar map_1_to_8[2] = {
456 0, 255
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;
477 return res;
481 static QRgb* qgl_create_rgb_palette(const PIXELFORMATDESCRIPTOR* pfd)
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);
496 const int syscol_indices[12] = {
497 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
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
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]);
515 return pal;
518 static QGLFormat pfdToQGLFormat(const PIXELFORMATDESCRIPTOR* pfd)
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;
546 NB! requires a current GL context to work
548 QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
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;
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
572 PFNWGLGETPIXELFORMATATTRIBIVARB wglGetPixelFormatAttribivARB =
573 (PFNWGLGETPIXELFORMATATTRIBIVARB) wglGetProcAddress("wglGetPixelFormatAttribivARB");
575 if (wglGetPixelFormatAttribivARB
576 && wglGetPixelFormatAttribivARB(hdc, pfi, 0, i,
577 iAttributes.constData(),
578 iValues.data()))
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]);
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;
631 Creates a temporary GL context and makes it current
632 - cleans up when the object is destructed.
635 Q_GUI_EXPORT const QString qt_getRegisteredWndClass();
637 class QGLTempContext
639 public:
640 QGLTempContext(bool directRendering, QWidget *parent = 0)
642 QString windowClassName = qt_getRegisteredWndClass();
643 if (parent && !parent->internalWinId())
644 parent = parent->nativeParentWidget();
645 QT_WA({
646 const TCHAR *cname = (TCHAR*)windowClassName.utf16();
647 dmy_id = CreateWindow(cname, 0, 0, 0, 0, 1, 1,
648 parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
649 } , {
650 dmy_id = CreateWindowA(windowClassName.toLatin1(), 0, 0, 0, 0, 1, 1,
651 parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
654 dmy_pdc = GetDC(dmy_id);
655 PIXELFORMATDESCRIPTOR dmy_pfd;
656 memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
657 dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
658 dmy_pfd.nVersion = 1;
659 dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
660 dmy_pfd.iPixelType = PFD_TYPE_RGBA;
661 if (!directRendering)
662 dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
664 int dmy_pf = ChoosePixelFormat(dmy_pdc, &dmy_pfd);
665 SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd);
666 dmy_rc = wglCreateContext(dmy_pdc);
667 wglMakeCurrent(dmy_pdc, dmy_rc);
670 ~QGLTempContext() {
671 wglMakeCurrent(dmy_pdc, 0);
672 wglDeleteContext(dmy_rc);
673 ReleaseDC(dmy_id, dmy_pdc);
674 DestroyWindow(dmy_id);
677 HDC dmy_pdc;
678 HGLRC dmy_rc;
679 WId dmy_id;
682 bool QGLContext::chooseContext(const QGLContext* shareContext)
684 Q_D(QGLContext);
685 // workaround for matrox driver:
686 // make a cheap call to opengl to force loading of DLL
687 if (!opengl32dll) {
688 GLint params;
689 glGetIntegerv(GL_DEPTH_BITS, &params);
690 opengl32dll = true;
693 bool result = true;
694 HDC myDc;
695 QWidget *widget = 0;
697 if (deviceIsPixmap()) {
698 if (d->glFormat.plane())
699 return false; // Pixmaps can't have overlay
700 d->win = 0;
701 HDC display_dc = GetDC(0);
702 myDc = d->hbitmap_hdc = CreateCompatibleDC(display_dc);
703 QPixmap *px = static_cast<QPixmap *>(d->paintDevice);
705 BITMAPINFO bmi;
706 memset(&bmi, 0, sizeof(bmi));
707 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
708 bmi.bmiHeader.biWidth = px->width();
709 bmi.bmiHeader.biHeight = px->height();
710 bmi.bmiHeader.biPlanes = 1;
711 bmi.bmiHeader.biBitCount = 32;
712 bmi.bmiHeader.biCompression = BI_RGB;
713 d->hbitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, 0, 0, 0);
714 SelectObject(myDc, d->hbitmap);
715 ReleaseDC(0, display_dc);
716 } else {
717 widget = static_cast<QWidget *>(d->paintDevice);
718 d->win = widget->winId();
719 myDc = GetDC(d->win);
722 // NB! the QGLTempContext object is needed for the
723 // wglGetProcAddress() calls to succeed and are absolutely
724 // necessary - don't remove!
725 QGLTempContext tmp_ctx(d->glFormat.directRendering(), widget);
727 if (!myDc) {
728 qWarning("QGLContext::chooseContext(): Paint device cannot be null");
729 result = false;
730 goto end;
733 if (d->glFormat.plane()) {
734 d->pixelFormatId = ((QGLWidget*)d->paintDevice)->context()->d_func()->pixelFormatId;
735 if (!d->pixelFormatId) { // I.e. the glwidget is invalid
736 qWarning("QGLContext::chooseContext(): Cannot create overlay context for invalid widget");
737 result = false;
738 goto end;
741 d->rc = wglCreateLayerContext(myDc, d->glFormat.plane());
742 if (!d->rc) {
743 qwglError("QGLContext::chooseContext()", "CreateLayerContext");
744 result = false;
745 goto end;
748 LAYERPLANEDESCRIPTOR lpfd;
749 wglDescribeLayerPlane(myDc, d->pixelFormatId, d->glFormat.plane(), sizeof(LAYERPLANEDESCRIPTOR), &lpfd);
750 d->glFormat.setDoubleBuffer(lpfd.dwFlags & LPD_DOUBLEBUFFER);
751 d->glFormat.setDepth(lpfd.cDepthBits);
752 d->glFormat.setRgba(lpfd.iPixelType == PFD_TYPE_RGBA);
753 if (d->glFormat.rgba()) {
754 if (d->glFormat.redBufferSize() != -1)
755 d->glFormat.setRedBufferSize(lpfd.cRedBits);
756 if (d->glFormat.greenBufferSize() != -1)
757 d->glFormat.setGreenBufferSize(lpfd.cGreenBits);
758 if (d->glFormat.blueBufferSize() != -1)
759 d->glFormat.setBlueBufferSize(lpfd.cBlueBits);
761 d->glFormat.setAlpha(lpfd.cAlphaBits);
762 d->glFormat.setAccum(lpfd.cAccumBits);
763 d->glFormat.setStencil(lpfd.cStencilBits);
764 d->glFormat.setStereo(lpfd.dwFlags & LPD_STEREO);
765 d->glFormat.setDirectRendering(false);
766 if (d->glFormat.depth())
767 d->glFormat.setDepthBufferSize(lpfd.cDepthBits);
768 if (d->glFormat.alpha())
769 d->glFormat.setAlphaBufferSize(lpfd.cAlphaBits);
770 if (d->glFormat.accum())
771 d->glFormat.setAccumBufferSize(lpfd.cAccumRedBits);
772 if (d->glFormat.stencil())
773 d->glFormat.setStencilBufferSize(lpfd.cStencilBits);
775 if (d->glFormat.rgba()) {
776 if (lpfd.dwFlags & LPD_TRANSPARENT)
777 d->transpColor = QColor(lpfd.crTransparent & 0xff,
778 (lpfd.crTransparent >> 8) & 0xff,
779 (lpfd.crTransparent >> 16) & 0xff);
780 else
781 d->transpColor = QColor(0, 0, 0);
783 else {
784 if (lpfd.dwFlags & LPD_TRANSPARENT)
785 d->transpColor = QColor(qRgb(1, 2, 3));//, lpfd.crTransparent);
786 else
787 d->transpColor = QColor(qRgb(1, 2, 3));//, 0);
789 d->cmap = new QGLCmap(1 << lpfd.cColorBits);
790 d->cmap->setEntry(lpfd.crTransparent, qRgb(1, 2, 3));//, QGLCmap::Reserved);
793 if (shareContext && shareContext->isValid()) {
794 QGLContext *share = const_cast<QGLContext *>(shareContext);
795 d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
796 share->d_func()->sharing = d->sharing;
799 goto end;
802 PIXELFORMATDESCRIPTOR pfd;
803 PIXELFORMATDESCRIPTOR realPfd;
804 d->pixelFormatId = choosePixelFormat(&pfd, myDc);
805 if (d->pixelFormatId == 0) {
806 qwglError("QGLContext::chooseContext()", "ChoosePixelFormat");
807 result = false;
808 goto end;
811 bool overlayRequested = d->glFormat.hasOverlay();
812 DescribePixelFormat(myDc, d->pixelFormatId, sizeof(PIXELFORMATDESCRIPTOR), &realPfd);
814 if (!deviceIsPixmap() && wglGetProcAddress("wglGetPixelFormatAttribivARB"))
815 d->glFormat = pfiToQGLFormat(myDc, d->pixelFormatId);
816 else
817 d->glFormat = pfdToQGLFormat(&realPfd);
819 d->glFormat.setOverlay(d->glFormat.hasOverlay() && overlayRequested);
821 if (deviceIsPixmap() && !(realPfd.dwFlags & PFD_DRAW_TO_BITMAP)) {
822 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context.");
823 result = false;
824 goto end;
827 if (deviceIsPixmap() &&
828 (((QPixmap*)d->paintDevice)->depth() != realPfd.cColorBits)) {
829 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context of suitable depth.");
830 result = false;
831 goto end;
834 if (!SetPixelFormat(myDc, d->pixelFormatId, &realPfd)) {
835 qwglError("QGLContext::chooseContext()", "SetPixelFormat");
836 result = false;
837 goto end;
840 if (!(d->rc = wglCreateLayerContext(myDc, 0))) {
841 qwglError("QGLContext::chooseContext()", "wglCreateContext");
842 result = false;
843 goto end;
846 if (shareContext && shareContext->isValid()) {
847 d->sharing = (wglShareLists(shareContext->d_func()->rc, d->rc) != 0);
848 const_cast<QGLContext *>(shareContext)->d_func()->sharing = d->sharing;
851 if(!deviceIsPixmap()) {
852 QRgb* pal = qgl_create_rgb_palette(&realPfd);
853 if (pal) {
854 QGLColormap cmap;
855 cmap.setEntries(256, pal);
856 ((QGLWidget*)d->paintDevice)->setColormap(cmap);
857 delete[] pal;
862 end:
863 // vblanking
864 wglMakeCurrent(myDc, d->rc);
865 typedef BOOL (APIENTRYP PFNWGLSWAPINTERVALEXT) (int interval);
866 typedef int (APIENTRYP PFNWGLGETSWAPINTERVALEXT) (void);
867 PFNWGLSWAPINTERVALEXT wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXT) wglGetProcAddress("wglSwapIntervalEXT");
868 PFNWGLGETSWAPINTERVALEXT wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXT) wglGetProcAddress("wglGetSwapIntervalEXT");
869 if (wglSwapIntervalEXT && wglGetSwapIntervalEXT) {
870 if (d->reqFormat.swapInterval() != -1)
871 wglSwapIntervalEXT(d->reqFormat.swapInterval());
872 d->glFormat.setSwapInterval(wglGetSwapIntervalEXT());
875 if (d->win)
876 ReleaseDC(d->win, myDc);
877 return result;
882 static bool qLogEq(bool a, bool b)
884 return (((!a) && (!b)) || (a && b));
888 See qgl.cpp for qdoc comment.
890 int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
892 Q_D(QGLContext);
893 // workaround for matrox driver:
894 // make a cheap call to opengl to force loading of DLL
895 if (!opengl32dll) {
896 GLint params;
897 glGetIntegerv(GL_DEPTH_BITS, &params);
898 opengl32dll = true;
901 PFNWGLCHOOSEPIXELFORMATARB wglChoosePixelFormatARB =
902 (PFNWGLCHOOSEPIXELFORMATARB) wglGetProcAddress("wglChoosePixelFormatARB");
903 int chosenPfi = 0;
904 if (!deviceIsPixmap() && wglChoosePixelFormatARB) {
905 bool valid;
906 int pixelFormat = 0;
907 uint numFormats = 0;
908 QVarLengthArray<int> iAttributes(40);
909 int i = 0;
910 iAttributes[i++] = WGL_ACCELERATION_ARB;
911 if (d->glFormat.directRendering())
912 iAttributes[i++] = WGL_FULL_ACCELERATION_ARB;
913 else
914 iAttributes[i++] = WGL_NO_ACCELERATION_ARB;
915 iAttributes[i++] = WGL_SUPPORT_OPENGL_ARB;
916 iAttributes[i++] = TRUE;
917 iAttributes[i++] = WGL_DRAW_TO_WINDOW_ARB;
918 iAttributes[i++] = TRUE;
919 iAttributes[i++] = WGL_COLOR_BITS_ARB;
920 iAttributes[i++] = 32;
921 iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB;
922 iAttributes[i++] = d->glFormat.doubleBuffer();
923 if (d->glFormat.stereo()) {
924 iAttributes[i++] = WGL_STEREO_ARB;
925 iAttributes[i++] = TRUE;
927 if (d->glFormat.depth()) {
928 iAttributes[i++] = WGL_DEPTH_BITS_ARB;
929 iAttributes[i++] = d->glFormat.depthBufferSize() == -1 ? 24 : d->glFormat.depthBufferSize();
931 iAttributes[i++] = WGL_PIXEL_TYPE_ARB;
932 if (d->glFormat.rgba()) {
933 iAttributes[i++] = WGL_TYPE_RGBA_ARB;
934 if (d->glFormat.redBufferSize() != -1) {
935 iAttributes[i++] = WGL_RED_BITS_ARB;
936 iAttributes[i++] = d->glFormat.redBufferSize();
938 if (d->glFormat.greenBufferSize() != -1) {
939 iAttributes[i++] = WGL_GREEN_BITS_ARB;
940 iAttributes[i++] = d->glFormat.greenBufferSize();
942 if (d->glFormat.blueBufferSize() != -1) {
943 iAttributes[i++] = WGL_BLUE_BITS_ARB;
944 iAttributes[i++] = d->glFormat.blueBufferSize();
946 } else {
947 iAttributes[i++] = WGL_TYPE_COLORINDEX_ARB;
949 if (d->glFormat.alpha()) {
950 iAttributes[i++] = WGL_ALPHA_BITS_ARB;
951 iAttributes[i++] = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize();
953 if (d->glFormat.accum()) {
954 iAttributes[i++] = WGL_ACCUM_BITS_ARB;
955 iAttributes[i++] = d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize();
957 if (d->glFormat.stencil()) {
958 iAttributes[i++] = WGL_STENCIL_BITS_ARB;
959 iAttributes[i++] = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize();
961 if (d->glFormat.hasOverlay()) {
962 iAttributes[i++] = WGL_NUMBER_OVERLAYS_ARB;
963 iAttributes[i++] = 1;
965 int si = 0;
966 bool trySampleBuffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
967 if (trySampleBuffers && d->glFormat.sampleBuffers()) {
968 iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
969 iAttributes[i++] = TRUE;
970 iAttributes[i++] = WGL_SAMPLES_ARB;
971 si = i;
972 iAttributes[i++] = d->glFormat.samples() == -1 ? 4 : d->glFormat.samples();
974 iAttributes[i] = 0;
976 do {
977 valid = wglChoosePixelFormatARB(pdc, iAttributes.constData(), 0, 1,
978 &pixelFormat, &numFormats);
979 if (trySampleBuffers && (!valid || numFormats < 1) && d->glFormat.sampleBuffers())
980 iAttributes[si] /= 2; // try different no. samples - we aim for the best one
981 else
982 break;
983 } while ((!valid || numFormats < 1) && iAttributes[si] > 1);
984 chosenPfi = pixelFormat;
987 if (!chosenPfi) { // fallback if wglChoosePixelFormatARB() failed
988 int pmDepth = deviceIsPixmap() ? ((QPixmap*)d->paintDevice)->depth() : 0;
989 PIXELFORMATDESCRIPTOR* p = (PIXELFORMATDESCRIPTOR*)dummyPfd;
990 memset(p, 0, sizeof(PIXELFORMATDESCRIPTOR));
991 p->nSize = sizeof(PIXELFORMATDESCRIPTOR);
992 p->nVersion = 1;
993 p->dwFlags = PFD_SUPPORT_OPENGL;
994 if (deviceIsPixmap())
995 p->dwFlags |= PFD_DRAW_TO_BITMAP;
996 else
997 p->dwFlags |= PFD_DRAW_TO_WINDOW;
998 if (!d->glFormat.directRendering())
999 p->dwFlags |= PFD_GENERIC_FORMAT;
1000 if (d->glFormat.doubleBuffer() && !deviceIsPixmap())
1001 p->dwFlags |= PFD_DOUBLEBUFFER;
1002 if (d->glFormat.stereo())
1003 p->dwFlags |= PFD_STEREO;
1004 if (d->glFormat.depth())
1005 p->cDepthBits = d->glFormat.depthBufferSize() == -1 ? 32 : d->glFormat.depthBufferSize();
1006 else
1007 p->dwFlags |= PFD_DEPTH_DONTCARE;
1008 if (d->glFormat.rgba()) {
1009 p->iPixelType = PFD_TYPE_RGBA;
1010 if (d->glFormat.redBufferSize() != -1)
1011 p->cRedBits = d->glFormat.redBufferSize();
1012 if (d->glFormat.greenBufferSize() != -1)
1013 p->cGreenBits = d->glFormat.greenBufferSize();
1014 if (d->glFormat.blueBufferSize() != -1)
1015 p->cBlueBits = d->glFormat.blueBufferSize();
1016 if (deviceIsPixmap())
1017 p->cColorBits = pmDepth;
1018 else
1019 p->cColorBits = 32;
1020 } else {
1021 p->iPixelType = PFD_TYPE_COLORINDEX;
1022 p->cColorBits = 8;
1024 if (d->glFormat.alpha())
1025 p->cAlphaBits = d->glFormat.alphaBufferSize() == -1 ? 8 : d->glFormat.alphaBufferSize();
1026 if (d->glFormat.accum()) {
1027 p->cAccumRedBits = p->cAccumGreenBits = p->cAccumBlueBits = p->cAccumAlphaBits =
1028 d->glFormat.accumBufferSize() == -1 ? 16 : d->glFormat.accumBufferSize();
1030 if (d->glFormat.stencil())
1031 p->cStencilBits = d->glFormat.stencilBufferSize() == -1 ? 8 : d->glFormat.stencilBufferSize();
1032 p->iLayerType = PFD_MAIN_PLANE;
1033 chosenPfi = ChoosePixelFormat(pdc, p);
1035 if (!chosenPfi)
1036 qErrnoWarning("QGLContext: ChoosePixelFormat failed");
1038 // Since the GDI function ChoosePixelFormat() does not handle
1039 // overlay and direct-rendering requests, we must roll our own here
1041 bool doSearch = chosenPfi <= 0;
1042 PIXELFORMATDESCRIPTOR pfd;
1043 QGLFormat fmt;
1044 if (!doSearch) {
1045 DescribePixelFormat(pdc, chosenPfi, sizeof(PIXELFORMATDESCRIPTOR),
1046 &pfd);
1047 fmt = pfdToQGLFormat(&pfd);
1048 if (d->glFormat.hasOverlay() && !fmt.hasOverlay())
1049 doSearch = true;
1050 else if (!qLogEq(d->glFormat.directRendering(), fmt.directRendering()))
1051 doSearch = true;
1052 else if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) ||
1053 pfd.cColorBits != pmDepth))
1054 doSearch = true;
1055 else if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))
1056 doSearch = true;
1057 else if (!qLogEq(d->glFormat.rgba(), fmt.rgba()))
1058 doSearch = true;
1061 if (doSearch) {
1062 int pfiMax = DescribePixelFormat(pdc, 0, 0, NULL);
1063 int bestScore = -1;
1064 int bestPfi = -1;
1065 for (int pfi = 1; pfi <= pfiMax; pfi++) {
1066 DescribePixelFormat(pdc, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
1067 if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
1068 continue;
1069 if (deviceIsPixmap() && (!(pfd.dwFlags & PFD_DRAW_TO_BITMAP) ||
1070 pfd.cColorBits != pmDepth))
1071 continue;
1072 if (!deviceIsPixmap() && !(pfd.dwFlags & PFD_DRAW_TO_WINDOW))
1073 continue;
1075 fmt = pfdToQGLFormat(&pfd);
1076 if (d->glFormat.hasOverlay() && !fmt.hasOverlay())
1077 continue;
1079 int score = pfd.cColorBits;
1080 if (qLogEq(d->glFormat.depth(), fmt.depth()))
1081 score += pfd.cDepthBits;
1082 if (qLogEq(d->glFormat.alpha(), fmt.alpha()))
1083 score += pfd.cAlphaBits;
1084 if (qLogEq(d->glFormat.accum(), fmt.accum()))
1085 score += pfd.cAccumBits;
1086 if (qLogEq(d->glFormat.stencil(), fmt.stencil()))
1087 score += pfd.cStencilBits;
1088 if (qLogEq(d->glFormat.doubleBuffer(), fmt.doubleBuffer()))
1089 score += 1000;
1090 if (qLogEq(d->glFormat.stereo(), fmt.stereo()))
1091 score += 2000;
1092 if (qLogEq(d->glFormat.directRendering(), fmt.directRendering()))
1093 score += 4000;
1094 if (qLogEq(d->glFormat.rgba(), fmt.rgba()))
1095 score += 8000;
1096 if (score > bestScore) {
1097 bestScore = score;
1098 bestPfi = pfi;
1102 if (bestPfi > 0)
1103 chosenPfi = bestPfi;
1106 return chosenPfi;
1111 void QGLContext::reset()
1113 Q_D(QGLContext);
1114 // workaround for matrox driver:
1115 // make a cheap call to opengl to force loading of DLL
1116 if (!opengl32dll) {
1117 GLint params;
1118 glGetIntegerv(GL_DEPTH_BITS, &params);
1119 opengl32dll = true;
1122 if (!d->valid)
1123 return;
1124 d->cleanup();
1125 doneCurrent();
1126 if (d->rc)
1127 wglDeleteContext(d->rc);
1128 d->rc = 0;
1129 if (d->win && d->dc)
1130 ReleaseDC(d->win, d->dc);
1131 if (deviceIsPixmap()) {
1132 DeleteDC(d->hbitmap_hdc);
1133 DeleteObject(d->hbitmap);
1134 d->hbitmap_hdc = 0;
1135 d->hbitmap = 0;
1137 d->dc = 0;
1138 d->win = 0;
1139 d->pixelFormatId = 0;
1140 d->sharing = false;
1141 d->valid = false;
1142 d->transpColor = QColor();
1143 delete d->cmap;
1144 d->cmap = 0;
1145 d->initDone = false;
1146 qgl_share_reg()->removeShare(this);
1150 // NOTE: In a multi-threaded environment, each thread has a current
1151 // context. If we want to make this code thread-safe, we probably
1152 // have to use TLS (thread local storage) for keeping current contexts.
1155 void QGLContext::makeCurrent()
1157 Q_D(QGLContext);
1158 if (d->rc == wglGetCurrentContext() || !d->valid) // already current
1159 return;
1160 if (d->win) {
1161 d->dc = GetDC(d->win);
1162 if (!d->dc) {
1163 qwglError("QGLContext::makeCurrent()", "GetDC()");
1164 return;
1166 } else if (deviceIsPixmap()) {
1167 d->dc = d->hbitmap_hdc;
1170 HPALETTE hpal = QColormap::hPal();
1171 if (hpal) {
1172 SelectPalette(d->dc, hpal, FALSE);
1173 RealizePalette(d->dc);
1175 if (d->glFormat.plane()) {
1176 wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE);
1179 if (wglMakeCurrent(d->dc, d->rc)) {
1180 if (!qgl_context_storage.hasLocalData() && QThread::currentThread())
1181 qgl_context_storage.setLocalData(new QGLThreadContext);
1182 if (qgl_context_storage.hasLocalData())
1183 qgl_context_storage.localData()->context = this;
1184 currentCtx = this;
1185 } else {
1186 qwglError("QGLContext::makeCurrent()", "wglMakeCurrent");
1191 void QGLContext::doneCurrent()
1193 Q_D(QGLContext);
1194 currentCtx = 0;
1195 wglMakeCurrent(0, 0);
1196 if (qgl_context_storage.hasLocalData())
1197 qgl_context_storage.localData()->context = 0;
1198 if (deviceIsPixmap() && d->hbitmap) {
1199 QPixmap *pm = static_cast<QPixmap *>(d->paintDevice);
1200 *pm = QPixmap::fromWinHBITMAP(d->hbitmap);
1202 if (d->win && d->dc) {
1203 ReleaseDC(d->win, d->dc);
1204 d->dc = 0;
1208 void QGLContext::swapBuffers() const
1210 Q_D(const QGLContext);
1211 if (d->dc && d->glFormat.doubleBuffer() && !deviceIsPixmap()) {
1212 if (d->glFormat.plane())
1213 wglSwapLayerBuffers(d->dc, WGL_SWAP_OVERLAY1);
1214 else {
1215 if (d->glFormat.hasOverlay())
1216 wglSwapLayerBuffers(d->dc, WGL_SWAP_MAIN_PLANE);
1217 else
1218 SwapBuffers(d->dc);
1224 QColor QGLContext::overlayTransparentColor() const
1226 return d_func()->transpColor;
1230 uint QGLContext::colorIndex(const QColor& c) const
1232 Q_D(const QGLContext);
1233 if (!isValid())
1234 return 0;
1235 if (d->cmap) {
1236 int idx = d->cmap->find(c.rgb());
1237 if (idx >= 0)
1238 return idx;
1239 if (d->dc && d->glFormat.plane()) {
1240 idx = d->cmap->allocate(c.rgb());
1241 if (idx >= 0) {
1242 COLORREF r = RGB(qRed(c.rgb()),qGreen(c.rgb()),qBlue(c.rgb()));
1243 wglSetLayerPaletteEntries(d->dc, d->glFormat.plane(), idx, 1, &r);
1244 wglRealizeLayerPalette(d->dc, d->glFormat.plane(), TRUE);
1245 return idx;
1248 return d->cmap->findNearest(c.rgb());
1250 QColormap cmap = QColormap::instance();
1251 return cmap.pixel(c) & 0x00ffffff; // Assumes standard palette
1254 void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
1256 if (!isValid())
1257 return;
1259 HDC display_dc = GetDC(0);
1260 HDC tmp_dc = CreateCompatibleDC(display_dc);
1261 HGDIOBJ old_font = SelectObject(tmp_dc, fnt.handle());
1263 ReleaseDC(0, display_dc);
1265 if (!wglUseFontBitmaps(tmp_dc, 0, 256, listBase))
1266 qWarning("QGLContext::generateFontDisplayLists: Could not generate display lists for font '%s'", fnt.family().toLatin1().data());
1268 SelectObject(tmp_dc, old_font);
1269 DeleteDC(tmp_dc);
1272 void *QGLContext::getProcAddress(const QString &proc) const
1274 return (void *)wglGetProcAddress(proc.toLatin1());
1277 /*****************************************************************************
1278 QGLWidget Win32/WGL-specific code
1279 *****************************************************************************/
1281 void QGLWidgetPrivate::init(QGLContext *ctx, const QGLWidget* shareWidget)
1283 Q_Q(QGLWidget);
1284 olcx = 0;
1285 initContext(ctx, shareWidget);
1287 if (q->isValid() && q->context()->format().hasOverlay()) {
1288 olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), q);
1289 if (!olcx->create(shareWidget ? shareWidget->overlayContext() : 0)) {
1290 delete olcx;
1291 olcx = 0;
1292 glcx->d_func()->glFormat.setOverlay(false);
1294 } else {
1295 olcx = 0;
1299 /*\internal
1300 Store color values in the given colormap.
1302 static void qStoreColors(HPALETTE cmap, const QGLColormap & cols)
1304 QRgb color;
1305 PALETTEENTRY pe;
1307 for (int i = 0; i < cols.size(); i++) {
1308 color = cols.entryRgb(i);
1309 pe.peRed = qRed(color);
1310 pe.peGreen = qGreen(color);
1311 pe.peBlue = qBlue(color);
1312 pe.peFlags = 0;
1314 SetPaletteEntries(cmap, i, 1, &pe);
1318 void QGLWidgetPrivate::updateColormap()
1320 Q_Q(QGLWidget);
1321 if (!cmap.handle())
1322 return;
1323 HDC hdc = GetDC(q->winId());
1324 SelectPalette(hdc, (HPALETTE) cmap.handle(), TRUE);
1325 qStoreColors((HPALETTE) cmap.handle(), cmap);
1326 RealizePalette(hdc);
1327 ReleaseDC(q->winId(), hdc);
1330 void QGLWidget::setMouseTracking(bool enable)
1332 QWidget::setMouseTracking(enable);
1336 void QGLWidget::resizeEvent(QResizeEvent *)
1338 Q_D(QGLWidget);
1339 if (!isValid())
1340 return;
1341 makeCurrent();
1342 if (!d->glcx->initialized())
1343 glInit();
1344 resizeGL(width(), height());
1345 if (d->olcx) {
1346 makeOverlayCurrent();
1347 resizeOverlayGL(width(), height());
1352 const QGLContext* QGLWidget::overlayContext() const
1354 return d_func()->olcx;
1358 void QGLWidget::makeOverlayCurrent()
1360 Q_D(QGLWidget);
1361 if (d->olcx) {
1362 d->olcx->makeCurrent();
1363 if (!d->olcx->initialized()) {
1364 initializeOverlayGL();
1365 d->olcx->setInitialized(true);
1371 void QGLWidget::updateOverlayGL()
1373 Q_D(QGLWidget);
1374 if (d->olcx) {
1375 makeOverlayCurrent();
1376 paintOverlayGL();
1377 if (d->olcx->format().doubleBuffer()) {
1378 if (d->autoSwap)
1379 d->olcx->swapBuffers();
1381 else {
1382 glFlush();
1388 void QGLWidget::setContext(QGLContext *context,
1389 const QGLContext* shareContext,
1390 bool deleteOldContext)
1392 Q_D(QGLWidget);
1393 if (context == 0) {
1394 qWarning("QGLWidget::setContext: Cannot set null context");
1395 return;
1397 if (!context->deviceIsPixmap() && context->device() != this) {
1398 qWarning("QGLWidget::setContext: Context must refer to this widget");
1399 return;
1402 if (d->glcx)
1403 d->glcx->doneCurrent();
1404 QGLContext* oldcx = d->glcx;
1405 d->glcx = context;
1407 bool doShow = false;
1408 if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) {
1409 // We already have a context and must therefore create a new
1410 // window since Windows does not permit setting a new OpenGL
1411 // context for a window that already has one set.
1412 doShow = isVisible();
1413 QWidget *pW = static_cast<QWidget *>(parent());
1414 QPoint pos = geometry().topLeft();
1415 setParent(pW, windowFlags());
1416 move(pos);
1419 if (!d->glcx->isValid()) {
1420 bool wasSharing = shareContext || oldcx && oldcx->isSharing();
1421 d->glcx->create(shareContext ? shareContext : oldcx);
1422 // the above is a trick to keep disp lists etc when a
1423 // QGLWidget has been reparented, so remove the sharing
1424 // flag if we don't actually have a sharing context.
1425 if (!wasSharing)
1426 d->glcx->d_ptr->sharing = false;
1429 if (deleteOldContext)
1430 delete oldcx;
1432 if (doShow)
1433 show();
1437 bool QGLWidgetPrivate::renderCxPm(QPixmap*)
1439 return false;
1442 void QGLWidgetPrivate::cleanupColormaps()
1444 Q_Q(QGLWidget);
1445 if (cmap.handle()) {
1446 HDC hdc = GetDC(q->winId());
1447 SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), FALSE);
1448 DeleteObject((HPALETTE) cmap.handle());
1449 ReleaseDC(q->winId(), hdc);
1450 cmap.setHandle(0);
1452 return;
1455 const QGLColormap & QGLWidget::colormap() const
1457 return d_func()->cmap;
1460 void QGLWidget::setColormap(const QGLColormap & c)
1462 Q_D(QGLWidget);
1463 d->cmap = c;
1465 if (d->cmap.handle()) { // already have an allocated cmap
1466 d->updateColormap();
1467 } else {
1468 LOGPALETTE *lpal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE)
1469 +c.size()*sizeof(PALETTEENTRY));
1470 lpal->palVersion = 0x300;
1471 lpal->palNumEntries = c.size();
1472 d->cmap.setHandle(CreatePalette(lpal));
1473 free(lpal);
1474 d->updateColormap();
1478 void QGLExtensions::init()
1480 static bool init_done = false;
1482 if (init_done)
1483 return;
1484 init_done = true;
1485 QGLTempContext temp_ctx(QGLFormat::defaultFormat().directRendering());
1486 init_extensions();
1489 QT_END_NAMESPACE