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 | |
56 | typedef bool (APIENTRY *PFNWGLGETPIXELFORMATATTRIBIVARB)(HDC hdc, |
57 | int iPixelFormat, |
58 | int iLayerPlane, |
59 | uint nAttributes, |
60 | const int *piAttributes, |
61 | int *piValues); |
62 | typedef bool (APIENTRY *PFNWGLCHOOSEPIXELFORMATARB)(HDC hdc, |
63 | const int *piAttribList, |
64 | const float *pfAttribFList, |
65 | uint nMaxFormats, |
66 | int *piFormats, |
67 | UINT *nNumFormats); |
68 | #ifndef WGL_ARB_multisample |
69 | #define WGL_SAMPLE_BUFFERS_ARB 0x2041 |
70 | #define WGL_SAMPLES_ARB 0x2042 |
71 | #endif |
72 | |
73 | #ifndef WGL_ARB_pixel_format |
74 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 |
75 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 |
76 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 |
77 | #define WGL_ACCELERATION_ARB 0x2003 |
78 | #define WGL_NEED_PALETTE_ARB 0x2004 |
79 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 |
80 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 |
81 | #define WGL_SWAP_METHOD_ARB 0x2007 |
82 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 |
83 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 |
84 | #define WGL_TRANSPARENT_ARB 0x200A |
85 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 |
86 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 |
87 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 |
88 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A |
89 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B |
90 | #define WGL_SHARE_DEPTH_ARB 0x200C |
91 | #define WGL_SHARE_STENCIL_ARB 0x200D |
92 | #define WGL_SHARE_ACCUM_ARB 0x200E |
93 | #define WGL_SUPPORT_GDI_ARB 0x200F |
94 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 |
95 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 |
96 | #define WGL_STEREO_ARB 0x2012 |
97 | #define WGL_PIXEL_TYPE_ARB 0x2013 |
98 | #define WGL_COLOR_BITS_ARB 0x2014 |
99 | #define WGL_RED_BITS_ARB 0x2015 |
100 | #define WGL_RED_SHIFT_ARB 0x2016 |
101 | #define WGL_GREEN_BITS_ARB 0x2017 |
102 | #define WGL_GREEN_SHIFT_ARB 0x2018 |
103 | #define WGL_BLUE_BITS_ARB 0x2019 |
104 | #define WGL_BLUE_SHIFT_ARB 0x201A |
105 | #define WGL_ALPHA_BITS_ARB 0x201B |
106 | #define WGL_ALPHA_SHIFT_ARB 0x201C |
107 | #define WGL_ACCUM_BITS_ARB 0x201D |
108 | #define WGL_ACCUM_RED_BITS_ARB 0x201E |
109 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F |
110 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 |
111 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 |
112 | #define WGL_DEPTH_BITS_ARB 0x2022 |
113 | #define WGL_STENCIL_BITS_ARB 0x2023 |
114 | #define WGL_AUX_BUFFERS_ARB 0x2024 |
115 | #define WGL_NO_ACCELERATION_ARB 0x2025 |
116 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 |
117 | #define WGL_FULL_ACCELERATION_ARB 0x2027 |
118 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 |
119 | #define WGL_SWAP_COPY_ARB 0x2029 |
120 | #define WGL_SWAP_UNDEFINED_ARB 0x202A |
121 | #define WGL_TYPE_RGBA_ARB 0x202B |
122 | #define WGL_TYPE_COLORINDEX_ARB 0x202C |
123 | #endif |
124 | |
125 | #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 | |
149 | QT_BEGIN_NAMESPACE |
150 | |
151 | class QGLCmapPrivate |
152 | { |
153 | public: |
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 | |
178 | class QGLCmapPrivate; |
179 | |
180 | class /*Q_EXPORT*/ QGLCmap |
181 | { |
182 | public: |
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 | |
205 | private: |
206 | void detach(); |
207 | QGLCmapPrivate* d; |
208 | }; |
209 | |
210 | |
211 | QGLCmap::QGLCmap(int maxSize) // add a bool prealloc? |
212 | { |
213 | d = new QGLCmapPrivate; |
214 | d->maxSize = maxSize; |
215 | } |
216 | |
217 | |
218 | QGLCmap::QGLCmap(const QGLCmap& map) |
219 | { |
220 | d = map.d; |
221 | d->ref(); |
222 | } |
223 | |
224 | |
225 | QGLCmap::~QGLCmap() |
226 | { |
227 | if (d && d->deref()) |
228 | delete d; |
229 | d = 0; |
230 | } |
231 | |
232 | |
233 | QGLCmap& 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 | |
243 | int QGLCmap::size() const |
244 | { |
245 | return d->colorArray.size(); |
246 | } |
247 | |
248 | |
249 | int QGLCmap::maxSize() const |
250 | { |
251 | return d->maxSize; |
252 | } |
253 | |
254 | |
255 | void 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 | |
273 | void 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 | |
292 | int 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 | |
301 | int 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 | |
333 | int 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 | |
368 | void 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 | |
392 | const QRgb* QGLCmap::colors() const |
393 | { |
394 | return d->colorArray.data(); |
395 | } |
396 | |
397 | |
398 | |
399 | /***************************************************************************** |
400 | QGLFormat Win32/WGL-specific code |
401 | *****************************************************************************/ |
402 | |
403 | |
404 | void 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 | |
423 | bool QGLFormat::hasOpenGL() |
424 | { |
425 | return true; |
426 | } |
427 | |
428 | static bool opengl32dll = false; |
429 | |
430 | bool 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, ¶ms); |
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 | |
471 | static 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 | |
505 | static 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 | |
542 | static 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 | */ |
572 | QGLFormat 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 | |
658 | Q_GUI_EXPORT const QString qt_getRegisteredWndClass(); |
659 | |
660 | class QGLTemporaryContextPrivate |
661 | { |
662 | public: |
663 | HDC dmy_pdc; |
664 | HGLRC dmy_rc; |
665 | HDC old_dc; |
666 | HGLRC old_context; |
667 | WId dmy_id; |
668 | }; |
669 | |
670 | QGLTemporaryContext::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 | |
699 | QGLTemporaryContext::~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 | |
709 | static 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 | |
770 | void QGLContextPrivate::updateFormatVersion() |
771 | { |
772 | const GLubyte *s = glGetString(GL_VERSION); |
773 | |
774 | if (!(s && s[0] >= |
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] - |
786 | int minor = s[2] - |
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 | |
817 | bool 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, ¶ms); |
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 | |
984 | end: |
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 | |
1007 | static bool qLogEq(bool a, bool b) |
1008 | { |
1009 | return (((!a) && (!b)) || (a && b)); |
1010 | } |
1011 | |
1012 | /* |
1013 | See qgl.cpp for qdoc comment. |
1014 | */ |
1015 | int 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, ¶ms); |
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 | |
1236 | void 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, ¶ms); |
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 | |
1281 | void 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 | |
1315 | void 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 | |
1331 | void 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 | |
1347 | QColor QGLContext::overlayTransparentColor() const |
1348 | { |
1349 | return d_func()->transpColor; |
1350 | } |
1351 | |
1352 | |
1353 | uint 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 | |
1377 | void 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 | |
1395 | void *QGLContext::getProcAddress(const QString &proc) const |
1396 | { |
1397 | return (void *)wglGetProcAddress(proc.toLatin1()); |
1398 | } |
1399 | |
1400 | /***************************************************************************** |
1401 | QGLWidget Win32/WGL-specific code |
1402 | *****************************************************************************/ |
1403 | |
1404 | void 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 | */ |
1425 | static 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 | |
1441 | void 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 | |
1453 | void QGLWidget::setMouseTracking(bool enable) |
1454 | { |
1455 | QWidget::setMouseTracking(enable); |
1456 | } |
1457 | |
1458 | |
1459 | void 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 | |
1475 | const QGLContext* QGLWidget::overlayContext() const |
1476 | { |
1477 | return d_func()->olcx; |
1478 | } |
1479 | |
1480 | |
1481 | void 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 | |
1494 | void 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 | |
1511 | void 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 | |
1560 | bool QGLWidgetPrivate::renderCxPm(QPixmap*) |
1561 | { |
1562 | return false; |
1563 | } |
1564 | |
1565 | void 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 | |
1578 | const QGLColormap & QGLWidget::colormap() const |
1579 | { |
1580 | return d_func()->cmap; |
1581 | } |
1582 | |
1583 | void 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 | |
1601 | QT_END_NAMESPACE |
1602 |
Warning: That file was not part of the compilation database. It may have many parsing errors.