Warning: That file was not part of the compilation database. It may have many parsing errors.

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

Warning: That file was not part of the compilation database. It may have many parsing errors.