source: trunk/src/opengl/qgl_win.cpp@ 591

Last change on this file since 591 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 46.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** 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.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
56typedef bool (APIENTRY *PFNWGLGETPIXELFORMATATTRIBIVARB)(HDC hdc,
57 int iPixelFormat,
58 int iLayerPlane,
59 uint nAttributes,
60 const int *piAttributes,
61 int *piValues);
62typedef 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
125QT_BEGIN_NAMESPACE
126
127class QGLCmapPrivate
128{
129public:
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
154class QGLCmapPrivate;
155
156class /*Q_EXPORT*/ QGLCmap
157{
158public:
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
181private:
182 void detach();
183 QGLCmapPrivate* d;
184};
185
186
187QGLCmap::QGLCmap(int maxSize) // add a bool prealloc?
188{
189 d = new QGLCmapPrivate;
190 d->maxSize = maxSize;
191}
192
193
194QGLCmap::QGLCmap(const QGLCmap& map)
195{
196 d = map.d;
197 d->ref();
198}
199
200
201QGLCmap::~QGLCmap()
202{
203 if (d && d->deref())
204 delete d;
205 d = 0;
206}
207
208
209QGLCmap& 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
219int QGLCmap::size() const
220{
221 return d->colorArray.size();
222}
223
224
225int QGLCmap::maxSize() const
226{
227 return d->maxSize;
228}
229
230
231void 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
249void 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
268int 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
277int 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
309int 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
344void 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
368const QRgb* QGLCmap::colors() const
369{
370 return d->colorArray.data();
371}
372
373
374
375/*****************************************************************************
376 QGLFormat Win32/WGL-specific code
377 *****************************************************************************/
378
379
380void 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
399bool QGLFormat::hasOpenGL()
400{
401 return true;
402}
403
404static bool opengl32dll = false;
405
406bool 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
447static 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
481static 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
518static 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*/
548QGLFormat 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
635Q_GUI_EXPORT const QString qt_getRegisteredWndClass();
636
637class QGLTempContext
638{
639public:
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
684bool 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);