1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
48 #include <private/qgl_p.h>
49 #include <qcolormap.h>
50 #include <qvarlengtharray.h>
54 #include <qt_windows.h>
56 typedef bool (APIENTRY
*PFNWGLGETPIXELFORMATATTRIBIVARB
)(HDC hdc
,
60 const int *piAttributes
,
62 typedef bool (APIENTRY
*PFNWGLCHOOSEPIXELFORMATARB
)(HDC hdc
,
63 const int *piAttribList
,
64 const float *pfAttribFList
,
68 #ifndef WGL_ARB_multisample
69 #define WGL_SAMPLE_BUFFERS_ARB 0x2041
70 #define WGL_SAMPLES_ARB 0x2042
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
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
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
154 QGLCmapPrivate() : count(1) { }
155 void ref() { ++count
; }
156 bool deref() { return !--count
; }
159 enum AllocState
{ UnAllocated
= 0, Allocated
= 0x01, Reserved
= 0x02 };
162 QVector
<uint
> colorArray
;
163 QVector
<quint8
> allocArray
;
164 QVector
<quint8
> contextArray
;
165 QMap
<uint
,int> colorMap
;
168 /*****************************************************************************
169 QColorMap class - temporarily here, until it is ready for prime time
170 *****************************************************************************/
172 /****************************************************************************
174 ** Definition of QColorMap class
176 ****************************************************************************/
178 class QGLCmapPrivate
;
180 class /*Q_EXPORT*/ QGLCmap
183 enum Flags
{ Reserved
= 0x01 };
185 QGLCmap(int maxSize
= 256);
186 QGLCmap(const QGLCmap
& map
);
189 QGLCmap
& operator=(const QGLCmap
& map
);
191 // isEmpty and/or isNull ?
195 void resize(int newSize
);
197 int find(QRgb color
) const;
198 int findNearest(QRgb color
) const;
199 int allocate(QRgb color
, uint flags
= 0, quint8 context
= 0);
201 void setEntry(int idx
, QRgb color
, uint flags
= 0, quint8 context
= 0);
203 const QRgb
* colors() const;
211 QGLCmap::QGLCmap(int maxSize
) // add a bool prealloc?
213 d
= new QGLCmapPrivate
;
214 d
->maxSize
= maxSize
;
218 QGLCmap::QGLCmap(const QGLCmap
& map
)
233 QGLCmap
& QGLCmap::operator=(const QGLCmap
& map
)
243 int QGLCmap::size() const
245 return d
->colorArray
.size();
249 int QGLCmap::maxSize() const
255 void QGLCmap::detach()
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
;
273 void QGLCmap::resize(int newSize
)
275 if (newSize
< 0 || newSize
> d
->maxSize
) {
276 qWarning("QGLCmap::resize(): size out of range");
279 int oldSize
= size();
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
);
292 int QGLCmap::find(QRgb color
) const
294 QMap
<uint
,int>::ConstIterator it
= d
->colorMap
.find(color
);
295 if (it
!= d
->colorMap
.end())
301 int QGLCmap::findNearest(QRgb color
) const
303 int idx
= find(color
);
306 int mapSize
= size();
307 int mindist
= 200000;
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
))
315 QRgb ci
= d
->colorArray
[i
];
319 dist
= rx
*rx
+ gx
*gx
+ bx
*bx
; // calculate distance
320 if (dist
< mindist
) { // minimal?
331 // Does not always allocate; returns existing c idx if found
333 int QGLCmap::allocate(QRgb color
, uint flags
, quint8 context
)
335 int idx
= find(color
);
339 int mapSize
= d
->colorArray
.size();
340 int newIdx
= d
->allocArray
.indexOf(QGLCmapPrivate::UnAllocated
);
342 if (newIdx
< 0) { // Must allocate more room
343 if (mapSize
< d
->maxSize
) {
349 //# add a bool param that says what to do in case no more room -
350 // fail (-1) or return nearest?
355 d
->colorArray
[newIdx
] = color
;
356 if (flags
& QGLCmap::Reserved
) {
357 d
->allocArray
[newIdx
] = QGLCmapPrivate::Reserved
;
360 d
->allocArray
[newIdx
] = QGLCmapPrivate::Allocated
;
361 d
->colorMap
.insert(color
, newIdx
);
363 d
->contextArray
[newIdx
] = context
;
368 void QGLCmap::setEntry(int idx
, QRgb color
, uint flags
, quint8 context
)
370 if (idx
< 0 || idx
>= d
->maxSize
) {
371 qWarning("QGLCmap::set(): Index out of range");
375 int mapSize
= size();
376 if (idx
>= mapSize
) {
380 d
->colorArray
[idx
] = color
;
381 if (flags
& QGLCmap::Reserved
) {
382 d
->allocArray
[idx
] = QGLCmapPrivate::Reserved
;
385 d
->allocArray
[idx
] = QGLCmapPrivate::Allocated
;
386 d
->colorMap
.insert(color
, idx
);
388 d
->contextArray
[idx
] = context
;
392 const QRgb
* QGLCmap::colors() const
394 return d
->colorArray
.data();
399 /*****************************************************************************
400 QGLFormat Win32/WGL-specific code
401 *****************************************************************************/
404 void qwglError(const char* method
, const char* func
)
409 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
411 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
412 (char*) &lpMsgBuf
, 0, 0);
413 qWarning("%s : %s failed: %s", method
, func
, lpMsgBuf
);
423 bool QGLFormat::hasOpenGL()
428 static bool opengl32dll
= false;
430 bool QGLFormat::hasOpenGLOverlays()
432 // workaround for matrox driver:
433 // make a cheap call to opengl to force loading of DLL
436 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
440 static bool checkDone
= false;
441 static bool hasOl
= false;
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
) {
461 ReleaseDC(0, display_dc
);
467 /*****************************************************************************
468 QGLContext Win32/WGL-specific code
469 *****************************************************************************/
471 static uchar
qgl_rgb_palette_comp(int idx
, uint nbits
, uint shift
)
473 const uchar map_3_to_8
[8] = {
474 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
476 const uchar map_2_to_8
[4] = {
479 const uchar map_1_to_8
[2] = {
483 uchar val
= (uchar
) (idx
>> shift
);
488 res
= map_1_to_8
[val
];
492 res
= map_2_to_8
[val
];
496 res
= map_3_to_8
[val
];
505 static QRgb
* qgl_create_rgb_palette(const PIXELFORMATDESCRIPTOR
* pfd
)
507 if ((pfd
->iPixelType
!= PFD_TYPE_RGBA
) ||
508 !(pfd
->dwFlags
& PFD_NEED_PALETTE
) ||
509 (pfd
->cColorBits
!= 8))
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
);
520 const int syscol_indices
[12] = {
521 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
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,
529 }; // colors #1 - #12 are not present in pal; gets added below
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]);
542 static QGLFormat
pfdToQGLFormat(const PIXELFORMATDESCRIPTOR
* pfd
)
545 fmt
.setDoubleBuffer(pfd
->dwFlags
& PFD_DOUBLEBUFFER
);
546 fmt
.setDepth(pfd
->cDepthBits
);
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
);
555 fmt
.setAlphaBufferSize(pfd
->cAlphaBits
);
556 fmt
.setAccum(pfd
->cAccumBits
);
558 fmt
.setAccumBufferSize(pfd
->cAccumRedBits
);
559 fmt
.setStencil(pfd
->cStencilBits
);
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);
570 NB! requires a current GL context to work
572 QGLFormat
pfiToQGLFormat(HDC hdc
, int pfi
)
575 QVarLengthArray
<int> iAttributes(40);
576 QVarLengthArray
<int> iValues(40);
578 bool has_sample_buffers
= QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers
;
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
596 PFNWGLGETPIXELFORMATATTRIBIVARB wglGetPixelFormatAttribivARB
=
597 (PFNWGLGETPIXELFORMATATTRIBIVARB
) wglGetProcAddress("wglGetPixelFormatAttribivARB");
599 if (wglGetPixelFormatAttribivARB
600 && wglGetPixelFormatAttribivARB(hdc
, pfi
, 0, i
,
601 iAttributes
.constData(),
604 fmt
.setDoubleBuffer(iValues
[0]);
605 fmt
.setDepth(iValues
[1]);
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]);
614 fmt
.setAlphaBufferSize(iValues
[6]);
615 fmt
.setAccum(iValues
[7]);
617 fmt
.setAccumBufferSize(iValues
[7]);
618 fmt
.setStencil(iValues
[8]);
620 fmt
.setStencilBufferSize(iValues
[8]);
621 fmt
.setStereo(iValues
[9]);
622 if (iValues
[10] == WGL_FULL_ACCELERATION_ARB
)
623 fmt
.setDirectRendering(true);
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]);
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();
655 QGLTemporaryContext implementation
658 Q_GUI_EXPORT
const QString
qt_getRegisteredWndClass();
660 class QGLTemporaryContextPrivate
670 QGLTemporaryContext::QGLTemporaryContext(bool directRendering
, QWidget
*parent
)
671 : d(new QGLTemporaryContextPrivate
)
673 QString windowClassName
= qt_getRegisteredWndClass();
674 if (parent
&& !parent
->internalWinId())
675 parent
= parent
->nativeParentWidget();
677 d
->dmy_id
= CreateWindow((const wchar_t *)windowClassName
.utf16(),
679 parent
? parent
->winId() : 0, 0, qWinAppInst(), 0);
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
;
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
);
699 QGLTemporaryContext::~QGLTemporaryContext()
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
);
709 static bool qgl_create_context(HDC hdc
, QGLContextPrivate
*d
, QGLContextPrivate
*shareContext
)
713 typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARB
)(HDC
, HGLRC
, const int *);
714 PFNWGLCREATECONTEXTATTRIBSARB wglCreateContextAttribsARB
=
715 (PFNWGLCREATECONTEXTATTRIBSARB
) wglGetProcAddress("wglCreateContextAttribsARB");
716 if (wglCreateContextAttribsARB
) {
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
;
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
;
731 if ((major
== 3 && minor
>= 2) || major
> 3) {
732 switch (d
->reqFormat
.profile()) {
733 case QGLFormat::NoProfile
:
735 case QGLFormat::CoreProfile
:
736 attributes
[attribIndex
++] = WGL_CONTEXT_PROFILE_MASK_ARB
;
737 attributes
[attribIndex
++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB
;
739 case QGLFormat::CompatibilityProfile
:
740 attributes
[attribIndex
++] = WGL_CONTEXT_PROFILE_MASK_ARB
;
741 attributes
[attribIndex
++] = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
;
744 qWarning("QGLContext::chooseContext(): Context profile not supported.");
749 if (d
->reqFormat
.plane() != 0) {
750 attributes
[attribIndex
++] = WGL_CONTEXT_LAYER_PLANE_ARB
;
751 attributes
[attribIndex
++] = d
->reqFormat
.plane();
754 attributes
[attribIndex
++] = 0; // Terminate list.
755 d
->rc
= wglCreateContextAttribsARB(hdc
, shareContext
&& shareContext
->valid
756 ? shareContext
->rc
: 0, attributes
);
759 shareContext
->sharing
= d
->sharing
= true;
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
);
770 void QGLContextPrivate::updateFormatVersion()
772 const GLubyte
*s
= glGetString(GL_VERSION
);
774 if (!(s
&& s
[0] >= '0' && s
[0] <= '9' && s
[1] == '.' && s
[2] >= '0' && s
[2] <= '9')) {
776 qWarning("QGLContext::chooseContext(): OpenGL version string is null.");
778 qWarning("QGLContext::chooseContext(): Unexpected OpenGL version string format.");
779 glFormat
.setVersion(0, 0);
780 glFormat
.setProfile(QGLFormat::NoProfile
);
781 glFormat
.setOption(QGL::DeprecatedFunctions
);
785 int major
= s
[0] - '0';
786 int minor
= s
[2] - '0';
787 glFormat
.setVersion(major
, minor
);
790 glFormat
.setProfile(QGLFormat::NoProfile
);
791 glFormat
.setOption(QGL::DeprecatedFunctions
);
794 if (major
> 3 || minor
>= 2)
795 glGetIntegerv(GL_CONTEXT_PROFILE_MASK
, &value
);
798 case WGL_CONTEXT_CORE_PROFILE_BIT_ARB
:
799 glFormat
.setProfile(QGLFormat::CoreProfile
);
801 case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
:
802 glFormat
.setProfile(QGLFormat::CompatibilityProfile
);
805 glFormat
.setProfile(QGLFormat::NoProfile
);
809 glGetIntegerv(GL_CONTEXT_FLAGS
, &value
);
810 if (value
& GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
)
811 glFormat
.setOption(QGL::NoDeprecatedFunctions
);
813 glFormat
.setOption(QGL::DeprecatedFunctions
);
817 bool QGLContext::chooseContext(const QGLContext
* shareContext
)
819 QGLContextPrivate
*share
= shareContext
? const_cast<QGLContext
*>(shareContext
)->d_func() : 0;
822 // workaround for matrox driver:
823 // make a cheap call to opengl to force loading of DLL
826 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
834 if (deviceIsPixmap()) {
835 if (d
->glFormat
.plane())
836 return false; // Pixmaps can't have overlay
838 HDC display_dc
= GetDC(0);
839 myDc
= d
->hbitmap_hdc
= CreateCompatibleDC(display_dc
);
840 QPixmap
*px
= static_cast<QPixmap
*>(d
->paintDevice
);
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
);
854 widget
= static_cast<QWidget
*>(d
->paintDevice
);
855 d
->win
= widget
->winId();
856 myDc
= GetDC(d
->win
);
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
);
865 qWarning("QGLContext::chooseContext(): Paint device cannot be null");
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");
878 if (!qgl_create_context(myDc
, d
, share
)) {
879 qwglError("QGLContext::chooseContext()", "CreateLayerContext");
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
);
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
);
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);
917 d
->transpColor
= QColor(0, 0, 0);
920 if (lpfd
.dwFlags
& LPD_TRANSPARENT
)
921 d
->transpColor
= QColor(qRgb(1, 2, 3));//, lpfd.crTransparent);
923 d
->transpColor
= QColor(qRgb(1, 2, 3));//, 0);
925 d
->cmap
= new QGLCmap(1 << lpfd
.cColorBits
);
926 d
->cmap
->setEntry(lpfd
.crTransparent
, qRgb(1, 2, 3));//, QGLCmap::Reserved);
929 PIXELFORMATDESCRIPTOR pfd
;
930 PIXELFORMATDESCRIPTOR realPfd
;
931 d
->pixelFormatId
= choosePixelFormat(&pfd
, myDc
);
932 if (d
->pixelFormatId
== 0) {
933 qwglError("QGLContext::chooseContext()", "ChoosePixelFormat");
938 bool overlayRequested
= d
->glFormat
.hasOverlay();
939 DescribePixelFormat(myDc
, d
->pixelFormatId
, sizeof(PIXELFORMATDESCRIPTOR
), &realPfd
);
941 if (!deviceIsPixmap() && wglGetProcAddress("wglGetPixelFormatAttribivARB"))
942 d
->glFormat
= pfiToQGLFormat(myDc
, d
->pixelFormatId
);
944 d
->glFormat
= pfdToQGLFormat(&realPfd
);
946 d
->glFormat
.setOverlay(d
->glFormat
.hasOverlay() && overlayRequested
);
948 if (deviceIsPixmap() && !(realPfd
.dwFlags
& PFD_DRAW_TO_BITMAP
)) {
949 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context.");
954 if (deviceIsPixmap() &&
955 (((QPixmap
*)d
->paintDevice
)->depth() != realPfd
.cColorBits
)) {
956 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context of suitable depth.");
961 if (!SetPixelFormat(myDc
, d
->pixelFormatId
, &realPfd
)) {
962 qwglError("QGLContext::chooseContext()", "SetPixelFormat");
967 if (!qgl_create_context(myDc
, d
, share
)) {
968 qwglError("QGLContext::chooseContext()", "wglCreateContext");
973 if(!deviceIsPixmap()) {
974 QRgb
* pal
= qgl_create_rgb_palette(&realPfd
);
977 cmap
.setEntries(256, pal
);
978 ((QGLWidget
*)d
->paintDevice
)->setColormap(cmap
);
986 wglMakeCurrent(myDc
, d
->rc
);
988 d
->updateFormatVersion();
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());
1001 ReleaseDC(d
->win
, myDc
);
1007 static bool qLogEq(bool a
, bool b
)
1009 return (((!a
) && (!b
)) || (a
&& b
));
1013 See qgl.cpp for qdoc comment.
1015 int QGLContext::choosePixelFormat(void* dummyPfd
, HDC pdc
)
1018 // workaround for matrox driver:
1019 // make a cheap call to opengl to force loading of DLL
1022 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
1026 PFNWGLCHOOSEPIXELFORMATARB wglChoosePixelFormatARB
=
1027 (PFNWGLCHOOSEPIXELFORMATARB
) wglGetProcAddress("wglChoosePixelFormatARB");
1029 if (!deviceIsPixmap() && wglChoosePixelFormatARB
) {
1031 int pixelFormat
= 0;
1032 uint numFormats
= 0;
1033 QVarLengthArray
<int> iAttributes(40);
1035 iAttributes
[i
++] = WGL_ACCELERATION_ARB
;
1036 if (d
->glFormat
.directRendering())
1037 iAttributes
[i
++] = WGL_FULL_ACCELERATION_ARB
;
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
++] = 32;
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
;
1052 if (d
->glFormat
.depth()) {
1053 iAttributes
[i
++] = WGL_DEPTH_BITS_ARB
;
1054 iAttributes
[i
++] = d
->glFormat
.depthBufferSize() == -1 ? 24 : d
->glFormat
.depthBufferSize();
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();
1063 if (d
->glFormat
.greenBufferSize() != -1) {
1064 iAttributes
[i
++] = WGL_GREEN_BITS_ARB
;
1065 iAttributes
[i
++] = d
->glFormat
.greenBufferSize();
1067 if (d
->glFormat
.blueBufferSize() != -1) {
1068 iAttributes
[i
++] = WGL_BLUE_BITS_ARB
;
1069 iAttributes
[i
++] = d
->glFormat
.blueBufferSize();
1072 iAttributes
[i
++] = WGL_TYPE_COLORINDEX_ARB
;
1074 if (d
->glFormat
.alpha()) {
1075 iAttributes
[i
++] = WGL_ALPHA_BITS_ARB
;
1076 iAttributes
[i
++] = d
->glFormat
.alphaBufferSize() == -1 ? 8 : d
->glFormat
.alphaBufferSize();
1078 if (d
->glFormat
.accum()) {
1079 iAttributes
[i
++] = WGL_ACCUM_BITS_ARB
;
1080 iAttributes
[i
++] = d
->glFormat
.accumBufferSize() == -1 ? 16 : d
->glFormat
.accumBufferSize();
1082 if (d
->glFormat
.stencil()) {
1083 iAttributes
[i
++] = WGL_STENCIL_BITS_ARB
;
1084 iAttributes
[i
++] = d
->glFormat
.stencilBufferSize() == -1 ? 8 : d
->glFormat
.stencilBufferSize();
1086 if (d
->glFormat
.hasOverlay()) {
1087 iAttributes
[i
++] = WGL_NUMBER_OVERLAYS_ARB
;
1088 iAttributes
[i
++] = 1;
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
;
1097 iAttributes
[i
++] = d
->glFormat
.samples() == -1 ? 4 : d
->glFormat
.samples();
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
1108 } while ((!valid
|| numFormats
< 1) && iAttributes
[si
] > 1);
1109 chosenPfi
= pixelFormat
;
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
);
1118 p
->dwFlags
= PFD_SUPPORT_OPENGL
;
1119 if (deviceIsPixmap())
1120 p
->dwFlags
|= PFD_DRAW_TO_BITMAP
;
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();
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
;
1146 p
->iPixelType
= PFD_TYPE_COLORINDEX
;
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();
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
);
1161 qErrnoWarning("QGLContext: ChoosePixelFormat failed");
1163 // Since the GDI function ChoosePixelFormat() does not handle
1164 // overlay and direct-rendering requests, we must roll our own here
1166 bool doSearch
= chosenPfi
<= 0;
1167 PIXELFORMATDESCRIPTOR pfd
;
1170 DescribePixelFormat(pdc
, chosenPfi
, sizeof(PIXELFORMATDESCRIPTOR
),
1172 fmt
= pfdToQGLFormat(&pfd
);
1173 if (d
->glFormat
.hasOverlay() && !fmt
.hasOverlay())
1175 else if (!qLogEq(d
->glFormat
.directRendering(), fmt
.directRendering()))
1177 else if (deviceIsPixmap() && (!(pfd
.dwFlags
& PFD_DRAW_TO_BITMAP
) ||
1178 pfd
.cColorBits
!= pmDepth
))
1180 else if (!deviceIsPixmap() && !(pfd
.dwFlags
& PFD_DRAW_TO_WINDOW
))
1182 else if (!qLogEq(d
->glFormat
.rgba(), fmt
.rgba()))
1187 int pfiMax
= DescribePixelFormat(pdc
, 0, 0, NULL
);
1190 for (int pfi
= 1; pfi
<= pfiMax
; pfi
++) {
1191 DescribePixelFormat(pdc
, pfi
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
1192 if (!(pfd
.dwFlags
& PFD_SUPPORT_OPENGL
))
1194 if (deviceIsPixmap() && (!(pfd
.dwFlags
& PFD_DRAW_TO_BITMAP
) ||
1195 pfd
.cColorBits
!= pmDepth
))
1197 if (!deviceIsPixmap() && !(pfd
.dwFlags
& PFD_DRAW_TO_WINDOW
))
1200 fmt
= pfdToQGLFormat(&pfd
);
1201 if (d
->glFormat
.hasOverlay() && !fmt
.hasOverlay())
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()))
1215 if (qLogEq(d
->glFormat
.stereo(), fmt
.stereo()))
1217 if (qLogEq(d
->glFormat
.directRendering(), fmt
.directRendering()))
1219 if (qLogEq(d
->glFormat
.rgba(), fmt
.rgba()))
1221 if (score
> bestScore
) {
1228 chosenPfi
= bestPfi
;
1236 void QGLContext::reset()
1239 // workaround for matrox driver:
1240 // make a cheap call to opengl to force loading of DLL
1243 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
1252 wglDeleteContext(d
->rc
);
1254 if (d
->win
&& d
->dc
)
1255 ReleaseDC(d
->win
, d
->dc
);
1256 if (deviceIsPixmap()) {
1257 DeleteDC(d
->hbitmap_hdc
);
1258 DeleteObject(d
->hbitmap
);
1264 d
->pixelFormatId
= 0;
1267 d
->transpColor
= QColor();
1270 d
->initDone
= false;
1271 QGLContextGroup::removeShare(this);
1275 // NOTE: In a multi-threaded environment, each thread has a current
1276 // context. If we want to make this code thread-safe, we probably
1277 // have to use TLS (thread local storage) for keeping current contexts.
1280 void QGLContext::makeCurrent()
1283 if (d
->rc
== wglGetCurrentContext() || !d
->valid
) // already current
1286 d
->dc
= GetDC(d
->win
);
1288 qwglError("QGLContext::makeCurrent()", "GetDC()");
1291 } else if (deviceIsPixmap()) {
1292 d
->dc
= d
->hbitmap_hdc
;
1295 HPALETTE hpal
= QColormap::hPal();
1297 SelectPalette(d
->dc
, hpal
, FALSE
);
1298 RealizePalette(d
->dc
);
1300 if (d
->glFormat
.plane()) {
1301 wglRealizeLayerPalette(d
->dc
, d
->glFormat
.plane(), TRUE
);
1304 if (wglMakeCurrent(d
->dc
, d
->rc
)) {
1305 QGLContextPrivate::setCurrentContext(this);
1307 qwglError("QGLContext::makeCurrent()", "wglMakeCurrent");
1312 void QGLContext::doneCurrent()
1315 wglMakeCurrent(0, 0);
1316 QGLContextPrivate::setCurrentContext(0);
1317 if (deviceIsPixmap() && d
->hbitmap
) {
1318 QPixmap
*pm
= static_cast<QPixmap
*>(d
->paintDevice
);
1319 *pm
= QPixmap::fromWinHBITMAP(d
->hbitmap
);
1321 if (d
->win
&& d
->dc
) {
1322 ReleaseDC(d
->win
, d
->dc
);
1327 void QGLContext::swapBuffers() const
1329 Q_D(const QGLContext
);
1330 if (d
->dc
&& d
->glFormat
.doubleBuffer() && !deviceIsPixmap()) {
1331 if (d
->glFormat
.plane())
1332 wglSwapLayerBuffers(d
->dc
, WGL_SWAP_OVERLAY1
);
1334 if (d
->glFormat
.hasOverlay())
1335 wglSwapLayerBuffers(d
->dc
, WGL_SWAP_MAIN_PLANE
);
1343 QColor
QGLContext::overlayTransparentColor() const
1345 return d_func()->transpColor
;
1349 uint
QGLContext::colorIndex(const QColor
& c
) const
1351 Q_D(const QGLContext
);
1355 int idx
= d
->cmap
->find(c
.rgb());
1358 if (d
->dc
&& d
->glFormat
.plane()) {
1359 idx
= d
->cmap
->allocate(c
.rgb());
1361 COLORREF r
= RGB(qRed(c
.rgb()),qGreen(c
.rgb()),qBlue(c
.rgb()));
1362 wglSetLayerPaletteEntries(d
->dc
, d
->glFormat
.plane(), idx
, 1, &r
);
1363 wglRealizeLayerPalette(d
->dc
, d
->glFormat
.plane(), TRUE
);
1367 return d
->cmap
->findNearest(c
.rgb());
1369 QColormap cmap
= QColormap::instance();
1370 return cmap
.pixel(c
) & 0x00ffffff; // Assumes standard palette
1373 void QGLContext::generateFontDisplayLists(const QFont
& fnt
, int listBase
)
1378 HDC display_dc
= GetDC(0);
1379 HDC tmp_dc
= CreateCompatibleDC(display_dc
);
1380 HGDIOBJ old_font
= SelectObject(tmp_dc
, fnt
.handle());
1382 ReleaseDC(0, display_dc
);
1384 if (!wglUseFontBitmaps(tmp_dc
, 0, 256, listBase
))
1385 qWarning("QGLContext::generateFontDisplayLists: Could not generate display lists for font '%s'", fnt
.family().toLatin1().data());
1387 SelectObject(tmp_dc
, old_font
);
1391 void *QGLContext::getProcAddress(const QString
&proc
) const
1393 return (void *)wglGetProcAddress(proc
.toLatin1());
1396 /*****************************************************************************
1397 QGLWidget Win32/WGL-specific code
1398 *****************************************************************************/
1400 void QGLWidgetPrivate::init(QGLContext
*ctx
, const QGLWidget
* shareWidget
)
1404 initContext(ctx
, shareWidget
);
1406 if (q
->isValid() && q
->context()->format().hasOverlay()) {
1407 olcx
= new QGLContext(QGLFormat::defaultOverlayFormat(), q
);
1408 if (!olcx
->create(shareWidget
? shareWidget
->overlayContext() : 0)) {
1411 glcx
->d_func()->glFormat
.setOverlay(false);
1419 Store color values in the given colormap.
1421 static void qStoreColors(HPALETTE cmap
, const QGLColormap
& cols
)
1426 for (int i
= 0; i
< cols
.size(); i
++) {
1427 color
= cols
.entryRgb(i
);
1428 pe
.peRed
= qRed(color
);
1429 pe
.peGreen
= qGreen(color
);
1430 pe
.peBlue
= qBlue(color
);
1433 SetPaletteEntries(cmap
, i
, 1, &pe
);
1437 void QGLWidgetPrivate::updateColormap()
1442 HDC hdc
= GetDC(q
->winId());
1443 SelectPalette(hdc
, (HPALETTE
) cmap
.handle(), TRUE
);
1444 qStoreColors((HPALETTE
) cmap
.handle(), cmap
);
1445 RealizePalette(hdc
);
1446 ReleaseDC(q
->winId(), hdc
);
1449 void QGLWidget::setMouseTracking(bool enable
)
1451 QWidget::setMouseTracking(enable
);
1455 void QGLWidget::resizeEvent(QResizeEvent
*)
1461 if (!d
->glcx
->initialized())
1463 resizeGL(width(), height());
1465 makeOverlayCurrent();
1466 resizeOverlayGL(width(), height());
1471 const QGLContext
* QGLWidget::overlayContext() const
1473 return d_func()->olcx
;
1477 void QGLWidget::makeOverlayCurrent()
1481 d
->olcx
->makeCurrent();
1482 if (!d
->olcx
->initialized()) {
1483 initializeOverlayGL();
1484 d
->olcx
->setInitialized(true);
1490 void QGLWidget::updateOverlayGL()
1494 makeOverlayCurrent();
1496 if (d
->olcx
->format().doubleBuffer()) {
1498 d
->olcx
->swapBuffers();
1507 void QGLWidget::setContext(QGLContext
*context
,
1508 const QGLContext
* shareContext
,
1509 bool deleteOldContext
)
1513 qWarning("QGLWidget::setContext: Cannot set null context");
1516 if (!context
->deviceIsPixmap() && context
->device() != this) {
1517 qWarning("QGLWidget::setContext: Context must refer to this widget");
1522 d
->glcx
->doneCurrent();
1523 QGLContext
* oldcx
= d
->glcx
;
1526 bool doShow
= false;
1527 if (oldcx
&& oldcx
->d_func()->win
== winId() && !d
->glcx
->deviceIsPixmap()) {
1528 // We already have a context and must therefore create a new
1529 // window since Windows does not permit setting a new OpenGL
1530 // context for a window that already has one set.
1531 doShow
= isVisible();
1532 QWidget
*pW
= static_cast<QWidget
*>(parent());
1533 QPoint pos
= geometry().topLeft();
1534 setParent(pW
, windowFlags());
1538 if (!d
->glcx
->isValid()) {
1539 bool wasSharing
= shareContext
|| (oldcx
&& oldcx
->isSharing());
1540 d
->glcx
->create(shareContext
? shareContext
: oldcx
);
1541 // the above is a trick to keep disp lists etc when a
1542 // QGLWidget has been reparented, so remove the sharing
1543 // flag if we don't actually have a sharing context.
1545 d
->glcx
->d_ptr
->sharing
= false;
1548 if (deleteOldContext
)
1556 bool QGLWidgetPrivate::renderCxPm(QPixmap
*)
1561 void QGLWidgetPrivate::cleanupColormaps()
1564 if (cmap
.handle()) {
1565 HDC hdc
= GetDC(q
->winId());
1566 SelectPalette(hdc
, (HPALETTE
) GetStockObject(DEFAULT_PALETTE
), FALSE
);
1567 DeleteObject((HPALETTE
) cmap
.handle());
1568 ReleaseDC(q
->winId(), hdc
);
1574 const QGLColormap
& QGLWidget::colormap() const
1576 return d_func()->cmap
;
1579 void QGLWidget::setColormap(const QGLColormap
& c
)
1584 if (d
->cmap
.handle()) { // already have an allocated cmap
1585 d
->updateColormap();
1587 LOGPALETTE
*lpal
= (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
)
1588 +c
.size()*sizeof(PALETTEENTRY
));
1589 lpal
->palVersion
= 0x300;
1590 lpal
->palNumEntries
= c
.size();
1591 d
->cmap
.setHandle(CreatePalette(lpal
));
1593 d
->updateColormap();