1 /****************************************************************************
3 ** Copyright (C) 2009 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
130 QGLCmapPrivate() : count(1) { }
131 void ref() { ++count
; }
132 bool deref() { return !--count
; }
135 enum AllocState
{ UnAllocated
= 0, Allocated
= 0x01, Reserved
= 0x02 };
138 QVector
<uint
> colorArray
;
139 QVector
<quint8
> allocArray
;
140 QVector
<quint8
> contextArray
;
141 QMap
<uint
,int> colorMap
;
144 /*****************************************************************************
145 QColorMap class - temporarily here, until it is ready for prime time
146 *****************************************************************************/
148 /****************************************************************************
150 ** Definition of QColorMap class
152 ****************************************************************************/
154 class QGLCmapPrivate
;
156 class /*Q_EXPORT*/ QGLCmap
159 enum Flags
{ Reserved
= 0x01 };
161 QGLCmap(int maxSize
= 256);
162 QGLCmap(const QGLCmap
& map
);
165 QGLCmap
& operator=(const QGLCmap
& map
);
167 // isEmpty and/or isNull ?
171 void resize(int newSize
);
173 int find(QRgb color
) const;
174 int findNearest(QRgb color
) const;
175 int allocate(QRgb color
, uint flags
= 0, quint8 context
= 0);
177 void setEntry(int idx
, QRgb color
, uint flags
= 0, quint8 context
= 0);
179 const QRgb
* colors() const;
187 QGLCmap::QGLCmap(int maxSize
) // add a bool prealloc?
189 d
= new QGLCmapPrivate
;
190 d
->maxSize
= maxSize
;
194 QGLCmap::QGLCmap(const QGLCmap
& map
)
209 QGLCmap
& QGLCmap::operator=(const QGLCmap
& map
)
219 int QGLCmap::size() const
221 return d
->colorArray
.size();
225 int QGLCmap::maxSize() const
231 void QGLCmap::detach()
235 QGLCmapPrivate
* newd
= new QGLCmapPrivate
;
236 newd
->maxSize
= d
->maxSize
;
237 newd
->colorArray
= d
->colorArray
;
238 newd
->allocArray
= d
->allocArray
;
239 newd
->contextArray
= d
->contextArray
;
240 newd
->colorArray
.detach();
241 newd
->allocArray
.detach();
242 newd
->contextArray
.detach();
243 newd
->colorMap
= d
->colorMap
;
249 void QGLCmap::resize(int newSize
)
251 if (newSize
< 0 || newSize
> d
->maxSize
) {
252 qWarning("QGLCmap::resize(): size out of range");
255 int oldSize
= size();
257 //if shrinking; remove the lost elems from colorMap
258 d
->colorArray
.resize(newSize
);
259 d
->allocArray
.resize(newSize
);
260 d
->contextArray
.resize(newSize
);
261 if (newSize
> oldSize
) {
262 memset(d
->allocArray
.data() + oldSize
, 0, newSize
- oldSize
);
263 memset(d
->contextArray
.data() + oldSize
, 0, newSize
- oldSize
);
268 int QGLCmap::find(QRgb color
) const
270 QMap
<uint
,int>::ConstIterator it
= d
->colorMap
.find(color
);
271 if (it
!= d
->colorMap
.end())
277 int QGLCmap::findNearest(QRgb color
) const
279 int idx
= find(color
);
282 int mapSize
= size();
283 int mindist
= 200000;
285 int g
= qGreen(color
);
286 int b
= qBlue(color
);
287 int rx
, gx
, bx
, dist
;
288 for (int i
=0; i
< mapSize
; i
++) {
289 if (!(d
->allocArray
[i
] & QGLCmapPrivate::Allocated
))
291 QRgb ci
= d
->colorArray
[i
];
295 dist
= rx
*rx
+ gx
*gx
+ bx
*bx
; // calculate distance
296 if (dist
< mindist
) { // minimal?
307 // Does not always allocate; returns existing c idx if found
309 int QGLCmap::allocate(QRgb color
, uint flags
, quint8 context
)
311 int idx
= find(color
);
315 int mapSize
= d
->colorArray
.size();
316 int newIdx
= d
->allocArray
.indexOf(QGLCmapPrivate::UnAllocated
);
318 if (newIdx
< 0) { // Must allocate more room
319 if (mapSize
< d
->maxSize
) {
325 //# add a bool param that says what to do in case no more room -
326 // fail (-1) or return nearest?
331 d
->colorArray
[newIdx
] = color
;
332 if (flags
& QGLCmap::Reserved
) {
333 d
->allocArray
[newIdx
] = QGLCmapPrivate::Reserved
;
336 d
->allocArray
[newIdx
] = QGLCmapPrivate::Allocated
;
337 d
->colorMap
.insert(color
, newIdx
);
339 d
->contextArray
[newIdx
] = context
;
344 void QGLCmap::setEntry(int idx
, QRgb color
, uint flags
, quint8 context
)
346 if (idx
< 0 || idx
>= d
->maxSize
) {
347 qWarning("QGLCmap::set(): Index out of range");
351 int mapSize
= size();
352 if (idx
>= mapSize
) {
356 d
->colorArray
[idx
] = color
;
357 if (flags
& QGLCmap::Reserved
) {
358 d
->allocArray
[idx
] = QGLCmapPrivate::Reserved
;
361 d
->allocArray
[idx
] = QGLCmapPrivate::Allocated
;
362 d
->colorMap
.insert(color
, idx
);
364 d
->contextArray
[idx
] = context
;
368 const QRgb
* QGLCmap::colors() const
370 return d
->colorArray
.data();
375 /*****************************************************************************
376 QGLFormat Win32/WGL-specific code
377 *****************************************************************************/
380 void qwglError(const char* method
, const char* func
)
385 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
387 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
388 (char*) &lpMsgBuf
, 0, 0);
389 qWarning("%s : %s failed: %s", method
, func
, lpMsgBuf
);
399 bool QGLFormat::hasOpenGL()
404 static bool opengl32dll
= false;
406 bool QGLFormat::hasOpenGLOverlays()
408 // workaround for matrox driver:
409 // make a cheap call to opengl to force loading of DLL
412 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
416 static bool checkDone
= false;
417 static bool hasOl
= false;
421 HDC display_dc
= GetDC(0);
422 int pfiMax
= DescribePixelFormat(display_dc
, 0, 0, NULL
);
423 PIXELFORMATDESCRIPTOR pfd
;
424 for (int pfi
= 1; pfi
<= pfiMax
; pfi
++) {
425 DescribePixelFormat(display_dc
, pfi
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
426 if ((pfd
.bReserved
& 0x0f) && (pfd
.dwFlags
& PFD_SUPPORT_OPENGL
)) {
427 // This format has overlays/underlays
428 LAYERPLANEDESCRIPTOR lpd
;
429 wglDescribeLayerPlane(display_dc
, pfi
, 1,
430 sizeof(LAYERPLANEDESCRIPTOR
), &lpd
);
431 if (lpd
.dwFlags
& LPD_SUPPORT_OPENGL
) {
437 ReleaseDC(0, display_dc
);
443 /*****************************************************************************
444 QGLContext Win32/WGL-specific code
445 *****************************************************************************/
447 static uchar
qgl_rgb_palette_comp(int idx
, uint nbits
, uint shift
)
449 const uchar map_3_to_8
[8] = {
450 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
452 const uchar map_2_to_8
[4] = {
455 const uchar map_1_to_8
[2] = {
459 uchar val
= (uchar
) (idx
>> shift
);
464 res
= map_1_to_8
[val
];
468 res
= map_2_to_8
[val
];
472 res
= map_3_to_8
[val
];
481 static QRgb
* qgl_create_rgb_palette(const PIXELFORMATDESCRIPTOR
* pfd
)
483 if ((pfd
->iPixelType
!= PFD_TYPE_RGBA
) ||
484 !(pfd
->dwFlags
& PFD_NEED_PALETTE
) ||
485 (pfd
->cColorBits
!= 8))
487 int numEntries
= 1 << pfd
->cColorBits
;
488 QRgb
* pal
= new QRgb
[numEntries
];
489 for (int i
= 0; i
< numEntries
; i
++) {
490 int r
= qgl_rgb_palette_comp(i
, pfd
->cRedBits
, pfd
->cRedShift
);
491 int g
= qgl_rgb_palette_comp(i
, pfd
->cGreenBits
, pfd
->cGreenShift
);
492 int b
= qgl_rgb_palette_comp(i
, pfd
->cBlueBits
, pfd
->cBlueShift
);
493 pal
[i
] = qRgb(r
, g
, b
);
496 const int syscol_indices
[12] = {
497 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
500 const uint syscols
[20] = {
501 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080,
502 0x008080, 0xc0c0c0, 0xc0dcc0, 0xa6caf0, 0xfffbf0, 0xa0a0a4,
503 0x808080, 0xff0000, 0x00ff00, 0xffff00, 0x0000ff, 0xff00ff,
505 }; // colors #1 - #12 are not present in pal; gets added below
507 if ((pfd
->cColorBits
== 8) &&
508 (pfd
->cRedBits
== 3) && (pfd
->cRedShift
== 0) &&
509 (pfd
->cGreenBits
== 3) && (pfd
->cGreenShift
== 3) &&
510 (pfd
->cBlueBits
== 2) && (pfd
->cBlueShift
== 6)) {
511 for (int j
= 0 ; j
< 12 ; j
++)
512 pal
[syscol_indices
[j
]] = QRgb(syscols
[j
+1]);
518 static QGLFormat
pfdToQGLFormat(const PIXELFORMATDESCRIPTOR
* pfd
)
521 fmt
.setDoubleBuffer(pfd
->dwFlags
& PFD_DOUBLEBUFFER
);
522 fmt
.setDepth(pfd
->cDepthBits
);
524 fmt
.setDepthBufferSize(pfd
->cDepthBits
);
525 fmt
.setRgba(pfd
->iPixelType
== PFD_TYPE_RGBA
);
526 fmt
.setRedBufferSize(pfd
->cRedBits
);
527 fmt
.setGreenBufferSize(pfd
->cGreenBits
);
528 fmt
.setBlueBufferSize(pfd
->cBlueBits
);
529 fmt
.setAlpha(pfd
->cAlphaBits
);
531 fmt
.setAlphaBufferSize(pfd
->cAlphaBits
);
532 fmt
.setAccum(pfd
->cAccumBits
);
534 fmt
.setAccumBufferSize(pfd
->cAccumRedBits
);
535 fmt
.setStencil(pfd
->cStencilBits
);
537 fmt
.setStencilBufferSize(pfd
->cStencilBits
);
538 fmt
.setStereo(pfd
->dwFlags
& PFD_STEREO
);
539 fmt
.setDirectRendering((pfd
->dwFlags
& PFD_GENERIC_ACCELERATED
) ||
540 !(pfd
->dwFlags
& PFD_GENERIC_FORMAT
));
541 fmt
.setOverlay((pfd
->bReserved
& 0x0f) != 0);
546 NB! requires a current GL context to work
548 QGLFormat
pfiToQGLFormat(HDC hdc
, int pfi
)
551 QVarLengthArray
<int> iAttributes(40);
552 QVarLengthArray
<int> iValues(40);
554 bool has_sample_buffers
= QGLExtensions::glExtensions
& QGLExtensions::SampleBuffers
;
556 iAttributes
[i
++] = WGL_DOUBLE_BUFFER_ARB
; // 0
557 iAttributes
[i
++] = WGL_DEPTH_BITS_ARB
; // 1
558 iAttributes
[i
++] = WGL_PIXEL_TYPE_ARB
; // 2
559 iAttributes
[i
++] = WGL_RED_BITS_ARB
; // 3
560 iAttributes
[i
++] = WGL_GREEN_BITS_ARB
; // 4
561 iAttributes
[i
++] = WGL_BLUE_BITS_ARB
; // 5
562 iAttributes
[i
++] = WGL_ALPHA_BITS_ARB
; // 6
563 iAttributes
[i
++] = WGL_ACCUM_BITS_ARB
; // 7
564 iAttributes
[i
++] = WGL_STENCIL_BITS_ARB
; // 8
565 iAttributes
[i
++] = WGL_STEREO_ARB
; // 9
566 iAttributes
[i
++] = WGL_ACCELERATION_ARB
; // 10
567 iAttributes
[i
++] = WGL_NUMBER_OVERLAYS_ARB
; // 11
568 if (has_sample_buffers
) {
569 iAttributes
[i
++] = WGL_SAMPLE_BUFFERS_ARB
; // 12
570 iAttributes
[i
++] = WGL_SAMPLES_ARB
; // 13
572 PFNWGLGETPIXELFORMATATTRIBIVARB wglGetPixelFormatAttribivARB
=
573 (PFNWGLGETPIXELFORMATATTRIBIVARB
) wglGetProcAddress("wglGetPixelFormatAttribivARB");
575 if (wglGetPixelFormatAttribivARB
576 && wglGetPixelFormatAttribivARB(hdc
, pfi
, 0, i
,
577 iAttributes
.constData(),
580 fmt
.setDoubleBuffer(iValues
[0]);
581 fmt
.setDepth(iValues
[1]);
583 fmt
.setDepthBufferSize(iValues
[1]);
584 fmt
.setRgba(iValues
[2] == WGL_TYPE_RGBA_ARB
);
585 fmt
.setRedBufferSize(iValues
[3]);
586 fmt
.setGreenBufferSize(iValues
[4]);
587 fmt
.setBlueBufferSize(iValues
[5]);
588 fmt
.setAlpha(iValues
[6]);
590 fmt
.setAlphaBufferSize(iValues
[6]);
591 fmt
.setAccum(iValues
[7]);
593 fmt
.setAccumBufferSize(iValues
[7]);
594 fmt
.setStencil(iValues
[8]);
596 fmt
.setStencilBufferSize(iValues
[8]);
597 fmt
.setStereo(iValues
[9]);
598 if (iValues
[10] == WGL_FULL_ACCELERATION_ARB
)
599 fmt
.setDirectRendering(true);
601 fmt
.setDirectRendering(false);
602 fmt
.setOverlay(iValues
[11]);
603 if (has_sample_buffers
) {
604 fmt
.setSampleBuffers(iValues
[12]);
605 if (fmt
.sampleBuffers())
606 fmt
.setSamples(iValues
[13]);
610 qDebug() << "values for pfi:" << pfi
;
611 qDebug() << "doublebuffer 0:" << fmt
.doubleBuffer();
612 qDebug() << "depthbuffer 1:" << fmt
.depthBufferSize();
613 qDebug() << "rgba 2:" << fmt
.rgba();
614 qDebug() << "red size 3:" << fmt
.redBufferSize();
615 qDebug() << "green size 4:" << fmt
.greenBufferSize();
616 qDebug() << "blue size 5:" << fmt
.blueBufferSize();
617 qDebug() << "alpha size 6:" << fmt
.alphaBufferSize();
618 qDebug() << "accum size 7:" << fmt
.accumBufferSize();
619 qDebug() << "stencil size 8:" << fmt
.stencilBufferSize();
620 qDebug() << "stereo 9:" << fmt
.stereo();
621 qDebug() << "direct 10:" << fmt
.directRendering();
622 qDebug() << "has overlays 11:" << fmt
.hasOverlay();
623 qDebug() << "sample buff 12:" << fmt
.sampleBuffers();
624 qDebug() << "num samples 13:" << fmt
.samples();
631 Creates a temporary GL context and makes it current
632 - cleans up when the object is destructed.
635 Q_GUI_EXPORT
const QString
qt_getRegisteredWndClass();
640 QGLTempContext(bool directRendering
, QWidget
*parent
= 0)
642 QString windowClassName
= qt_getRegisteredWndClass();
643 if (parent
&& !parent
->internalWinId())
644 parent
= parent
->nativeParentWidget();
646 dmy_id
= CreateWindow((const wchar_t *)windowClassName
.utf16(),
648 parent
? parent
->winId() : 0, 0, qWinAppInst(), 0);
650 dmy_pdc
= GetDC(dmy_id
);
651 PIXELFORMATDESCRIPTOR dmy_pfd
;
652 memset(&dmy_pfd
, 0, sizeof(PIXELFORMATDESCRIPTOR
));
653 dmy_pfd
.nSize
= sizeof(PIXELFORMATDESCRIPTOR
);
654 dmy_pfd
.nVersion
= 1;
655 dmy_pfd
.dwFlags
= PFD_SUPPORT_OPENGL
| PFD_DRAW_TO_WINDOW
;
656 dmy_pfd
.iPixelType
= PFD_TYPE_RGBA
;
657 if (!directRendering
)
658 dmy_pfd
.dwFlags
|= PFD_GENERIC_FORMAT
;
660 int dmy_pf
= ChoosePixelFormat(dmy_pdc
, &dmy_pfd
);
661 SetPixelFormat(dmy_pdc
, dmy_pf
, &dmy_pfd
);
662 dmy_rc
= wglCreateContext(dmy_pdc
);
663 old_dc
= wglGetCurrentDC();
664 old_context
= wglGetCurrentContext();
665 wglMakeCurrent(dmy_pdc
, dmy_rc
);
669 wglMakeCurrent(dmy_pdc
, 0);
670 wglDeleteContext(dmy_rc
);
671 ReleaseDC(dmy_id
, dmy_pdc
);
672 DestroyWindow(dmy_id
);
673 if (old_dc
&& old_context
)
674 wglMakeCurrent(old_dc
, old_context
);
684 bool QGLContext::chooseContext(const QGLContext
* shareContext
)
687 // workaround for matrox driver:
688 // make a cheap call to opengl to force loading of DLL
691 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
699 if (deviceIsPixmap()) {
700 if (d
->glFormat
.plane())
701 return false; // Pixmaps can't have overlay
703 HDC display_dc
= GetDC(0);
704 myDc
= d
->hbitmap_hdc
= CreateCompatibleDC(display_dc
);
705 QPixmap
*px
= static_cast<QPixmap
*>(d
->paintDevice
);
708 memset(&bmi
, 0, sizeof(bmi
));
709 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
710 bmi
.bmiHeader
.biWidth
= px
->width();
711 bmi
.bmiHeader
.biHeight
= px
->height();
712 bmi
.bmiHeader
.biPlanes
= 1;
713 bmi
.bmiHeader
.biBitCount
= 32;
714 bmi
.bmiHeader
.biCompression
= BI_RGB
;
715 d
->hbitmap
= CreateDIBSection(display_dc
, &bmi
, DIB_RGB_COLORS
, 0, 0, 0);
716 SelectObject(myDc
, d
->hbitmap
);
717 ReleaseDC(0, display_dc
);
719 widget
= static_cast<QWidget
*>(d
->paintDevice
);
720 d
->win
= widget
->winId();
721 myDc
= GetDC(d
->win
);
724 // NB! the QGLTempContext object is needed for the
725 // wglGetProcAddress() calls to succeed and are absolutely
726 // necessary - don't remove!
727 QGLTempContext
tmp_ctx(d
->glFormat
.directRendering(), widget
);
730 qWarning("QGLContext::chooseContext(): Paint device cannot be null");
735 if (d
->glFormat
.plane()) {
736 d
->pixelFormatId
= ((QGLWidget
*)d
->paintDevice
)->context()->d_func()->pixelFormatId
;
737 if (!d
->pixelFormatId
) { // I.e. the glwidget is invalid
738 qWarning("QGLContext::chooseContext(): Cannot create overlay context for invalid widget");
743 d
->rc
= wglCreateLayerContext(myDc
, d
->glFormat
.plane());
745 qwglError("QGLContext::chooseContext()", "CreateLayerContext");
750 LAYERPLANEDESCRIPTOR lpfd
;
751 wglDescribeLayerPlane(myDc
, d
->pixelFormatId
, d
->glFormat
.plane(), sizeof(LAYERPLANEDESCRIPTOR
), &lpfd
);
752 d
->glFormat
.setDoubleBuffer(lpfd
.dwFlags
& LPD_DOUBLEBUFFER
);
753 d
->glFormat
.setDepth(lpfd
.cDepthBits
);
754 d
->glFormat
.setRgba(lpfd
.iPixelType
== PFD_TYPE_RGBA
);
755 if (d
->glFormat
.rgba()) {
756 if (d
->glFormat
.redBufferSize() != -1)
757 d
->glFormat
.setRedBufferSize(lpfd
.cRedBits
);
758 if (d
->glFormat
.greenBufferSize() != -1)
759 d
->glFormat
.setGreenBufferSize(lpfd
.cGreenBits
);
760 if (d
->glFormat
.blueBufferSize() != -1)
761 d
->glFormat
.setBlueBufferSize(lpfd
.cBlueBits
);
763 d
->glFormat
.setAlpha(lpfd
.cAlphaBits
);
764 d
->glFormat
.setAccum(lpfd
.cAccumBits
);
765 d
->glFormat
.setStencil(lpfd
.cStencilBits
);
766 d
->glFormat
.setStereo(lpfd
.dwFlags
& LPD_STEREO
);
767 d
->glFormat
.setDirectRendering(false);
768 if (d
->glFormat
.depth())
769 d
->glFormat
.setDepthBufferSize(lpfd
.cDepthBits
);
770 if (d
->glFormat
.alpha())
771 d
->glFormat
.setAlphaBufferSize(lpfd
.cAlphaBits
);
772 if (d
->glFormat
.accum())
773 d
->glFormat
.setAccumBufferSize(lpfd
.cAccumRedBits
);
774 if (d
->glFormat
.stencil())
775 d
->glFormat
.setStencilBufferSize(lpfd
.cStencilBits
);
777 if (d
->glFormat
.rgba()) {
778 if (lpfd
.dwFlags
& LPD_TRANSPARENT
)
779 d
->transpColor
= QColor(lpfd
.crTransparent
& 0xff,
780 (lpfd
.crTransparent
>> 8) & 0xff,
781 (lpfd
.crTransparent
>> 16) & 0xff);
783 d
->transpColor
= QColor(0, 0, 0);
786 if (lpfd
.dwFlags
& LPD_TRANSPARENT
)
787 d
->transpColor
= QColor(qRgb(1, 2, 3));//, lpfd.crTransparent);
789 d
->transpColor
= QColor(qRgb(1, 2, 3));//, 0);
791 d
->cmap
= new QGLCmap(1 << lpfd
.cColorBits
);
792 d
->cmap
->setEntry(lpfd
.crTransparent
, qRgb(1, 2, 3));//, QGLCmap::Reserved);
795 if (shareContext
&& shareContext
->isValid()) {
796 QGLContext
*share
= const_cast<QGLContext
*>(shareContext
);
797 d
->sharing
= (wglShareLists(shareContext
->d_func()->rc
, d
->rc
) != 0);
798 share
->d_func()->sharing
= d
->sharing
;
804 PIXELFORMATDESCRIPTOR pfd
;
805 PIXELFORMATDESCRIPTOR realPfd
;
806 d
->pixelFormatId
= choosePixelFormat(&pfd
, myDc
);
807 if (d
->pixelFormatId
== 0) {
808 qwglError("QGLContext::chooseContext()", "ChoosePixelFormat");
813 bool overlayRequested
= d
->glFormat
.hasOverlay();
814 DescribePixelFormat(myDc
, d
->pixelFormatId
, sizeof(PIXELFORMATDESCRIPTOR
), &realPfd
);
816 if (!deviceIsPixmap() && wglGetProcAddress("wglGetPixelFormatAttribivARB"))
817 d
->glFormat
= pfiToQGLFormat(myDc
, d
->pixelFormatId
);
819 d
->glFormat
= pfdToQGLFormat(&realPfd
);
821 d
->glFormat
.setOverlay(d
->glFormat
.hasOverlay() && overlayRequested
);
823 if (deviceIsPixmap() && !(realPfd
.dwFlags
& PFD_DRAW_TO_BITMAP
)) {
824 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context.");
829 if (deviceIsPixmap() &&
830 (((QPixmap
*)d
->paintDevice
)->depth() != realPfd
.cColorBits
)) {
831 qWarning("QGLContext::chooseContext(): Failed to get pixmap rendering context of suitable depth.");
836 if (!SetPixelFormat(myDc
, d
->pixelFormatId
, &realPfd
)) {
837 qwglError("QGLContext::chooseContext()", "SetPixelFormat");
842 if (!(d
->rc
= wglCreateLayerContext(myDc
, 0))) {
843 qwglError("QGLContext::chooseContext()", "wglCreateContext");
848 if (shareContext
&& shareContext
->isValid()) {
849 d
->sharing
= (wglShareLists(shareContext
->d_func()->rc
, d
->rc
) != 0);
850 const_cast<QGLContext
*>(shareContext
)->d_func()->sharing
= d
->sharing
;
853 if(!deviceIsPixmap()) {
854 QRgb
* pal
= qgl_create_rgb_palette(&realPfd
);
857 cmap
.setEntries(256, pal
);
858 ((QGLWidget
*)d
->paintDevice
)->setColormap(cmap
);
866 wglMakeCurrent(myDc
, d
->rc
);
867 typedef BOOL (APIENTRYP PFNWGLSWAPINTERVALEXT
) (int interval
);
868 typedef int (APIENTRYP PFNWGLGETSWAPINTERVALEXT
) (void);
869 PFNWGLSWAPINTERVALEXT wglSwapIntervalEXT
= (PFNWGLSWAPINTERVALEXT
) wglGetProcAddress("wglSwapIntervalEXT");
870 PFNWGLGETSWAPINTERVALEXT wglGetSwapIntervalEXT
= (PFNWGLGETSWAPINTERVALEXT
) wglGetProcAddress("wglGetSwapIntervalEXT");
871 if (wglSwapIntervalEXT
&& wglGetSwapIntervalEXT
) {
872 if (d
->reqFormat
.swapInterval() != -1)
873 wglSwapIntervalEXT(d
->reqFormat
.swapInterval());
874 d
->glFormat
.setSwapInterval(wglGetSwapIntervalEXT());
878 ReleaseDC(d
->win
, myDc
);
884 static bool qLogEq(bool a
, bool b
)
886 return (((!a
) && (!b
)) || (a
&& b
));
890 See qgl.cpp for qdoc comment.
892 int QGLContext::choosePixelFormat(void* dummyPfd
, HDC pdc
)
895 // workaround for matrox driver:
896 // make a cheap call to opengl to force loading of DLL
899 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
903 PFNWGLCHOOSEPIXELFORMATARB wglChoosePixelFormatARB
=
904 (PFNWGLCHOOSEPIXELFORMATARB
) wglGetProcAddress("wglChoosePixelFormatARB");
906 if (!deviceIsPixmap() && wglChoosePixelFormatARB
) {
910 QVarLengthArray
<int> iAttributes(40);
912 iAttributes
[i
++] = WGL_ACCELERATION_ARB
;
913 if (d
->glFormat
.directRendering())
914 iAttributes
[i
++] = WGL_FULL_ACCELERATION_ARB
;
916 iAttributes
[i
++] = WGL_NO_ACCELERATION_ARB
;
917 iAttributes
[i
++] = WGL_SUPPORT_OPENGL_ARB
;
918 iAttributes
[i
++] = TRUE
;
919 iAttributes
[i
++] = WGL_DRAW_TO_WINDOW_ARB
;
920 iAttributes
[i
++] = TRUE
;
921 iAttributes
[i
++] = WGL_COLOR_BITS_ARB
;
922 iAttributes
[i
++] = 32;
923 iAttributes
[i
++] = WGL_DOUBLE_BUFFER_ARB
;
924 iAttributes
[i
++] = d
->glFormat
.doubleBuffer();
925 if (d
->glFormat
.stereo()) {
926 iAttributes
[i
++] = WGL_STEREO_ARB
;
927 iAttributes
[i
++] = TRUE
;
929 if (d
->glFormat
.depth()) {
930 iAttributes
[i
++] = WGL_DEPTH_BITS_ARB
;
931 iAttributes
[i
++] = d
->glFormat
.depthBufferSize() == -1 ? 24 : d
->glFormat
.depthBufferSize();
933 iAttributes
[i
++] = WGL_PIXEL_TYPE_ARB
;
934 if (d
->glFormat
.rgba()) {
935 iAttributes
[i
++] = WGL_TYPE_RGBA_ARB
;
936 if (d
->glFormat
.redBufferSize() != -1) {
937 iAttributes
[i
++] = WGL_RED_BITS_ARB
;
938 iAttributes
[i
++] = d
->glFormat
.redBufferSize();
940 if (d
->glFormat
.greenBufferSize() != -1) {
941 iAttributes
[i
++] = WGL_GREEN_BITS_ARB
;
942 iAttributes
[i
++] = d
->glFormat
.greenBufferSize();
944 if (d
->glFormat
.blueBufferSize() != -1) {
945 iAttributes
[i
++] = WGL_BLUE_BITS_ARB
;
946 iAttributes
[i
++] = d
->glFormat
.blueBufferSize();
949 iAttributes
[i
++] = WGL_TYPE_COLORINDEX_ARB
;
951 if (d
->glFormat
.alpha()) {
952 iAttributes
[i
++] = WGL_ALPHA_BITS_ARB
;
953 iAttributes
[i
++] = d
->glFormat
.alphaBufferSize() == -1 ? 8 : d
->glFormat
.alphaBufferSize();
955 if (d
->glFormat
.accum()) {
956 iAttributes
[i
++] = WGL_ACCUM_BITS_ARB
;
957 iAttributes
[i
++] = d
->glFormat
.accumBufferSize() == -1 ? 16 : d
->glFormat
.accumBufferSize();
959 if (d
->glFormat
.stencil()) {
960 iAttributes
[i
++] = WGL_STENCIL_BITS_ARB
;
961 iAttributes
[i
++] = d
->glFormat
.stencilBufferSize() == -1 ? 8 : d
->glFormat
.stencilBufferSize();
963 if (d
->glFormat
.hasOverlay()) {
964 iAttributes
[i
++] = WGL_NUMBER_OVERLAYS_ARB
;
965 iAttributes
[i
++] = 1;
968 bool trySampleBuffers
= QGLExtensions::glExtensions
& QGLExtensions::SampleBuffers
;
969 if (trySampleBuffers
&& d
->glFormat
.sampleBuffers()) {
970 iAttributes
[i
++] = WGL_SAMPLE_BUFFERS_ARB
;
971 iAttributes
[i
++] = TRUE
;
972 iAttributes
[i
++] = WGL_SAMPLES_ARB
;
974 iAttributes
[i
++] = d
->glFormat
.samples() == -1 ? 4 : d
->glFormat
.samples();
979 valid
= wglChoosePixelFormatARB(pdc
, iAttributes
.constData(), 0, 1,
980 &pixelFormat
, &numFormats
);
981 if (trySampleBuffers
&& (!valid
|| numFormats
< 1) && d
->glFormat
.sampleBuffers())
982 iAttributes
[si
] /= 2; // try different no. samples - we aim for the best one
985 } while ((!valid
|| numFormats
< 1) && iAttributes
[si
] > 1);
986 chosenPfi
= pixelFormat
;
989 if (!chosenPfi
) { // fallback if wglChoosePixelFormatARB() failed
990 int pmDepth
= deviceIsPixmap() ? ((QPixmap
*)d
->paintDevice
)->depth() : 0;
991 PIXELFORMATDESCRIPTOR
* p
= (PIXELFORMATDESCRIPTOR
*)dummyPfd
;
992 memset(p
, 0, sizeof(PIXELFORMATDESCRIPTOR
));
993 p
->nSize
= sizeof(PIXELFORMATDESCRIPTOR
);
995 p
->dwFlags
= PFD_SUPPORT_OPENGL
;
996 if (deviceIsPixmap())
997 p
->dwFlags
|= PFD_DRAW_TO_BITMAP
;
999 p
->dwFlags
|= PFD_DRAW_TO_WINDOW
;
1000 if (!d
->glFormat
.directRendering())
1001 p
->dwFlags
|= PFD_GENERIC_FORMAT
;
1002 if (d
->glFormat
.doubleBuffer() && !deviceIsPixmap())
1003 p
->dwFlags
|= PFD_DOUBLEBUFFER
;
1004 if (d
->glFormat
.stereo())
1005 p
->dwFlags
|= PFD_STEREO
;
1006 if (d
->glFormat
.depth())
1007 p
->cDepthBits
= d
->glFormat
.depthBufferSize() == -1 ? 32 : d
->glFormat
.depthBufferSize();
1009 p
->dwFlags
|= PFD_DEPTH_DONTCARE
;
1010 if (d
->glFormat
.rgba()) {
1011 p
->iPixelType
= PFD_TYPE_RGBA
;
1012 if (d
->glFormat
.redBufferSize() != -1)
1013 p
->cRedBits
= d
->glFormat
.redBufferSize();
1014 if (d
->glFormat
.greenBufferSize() != -1)
1015 p
->cGreenBits
= d
->glFormat
.greenBufferSize();
1016 if (d
->glFormat
.blueBufferSize() != -1)
1017 p
->cBlueBits
= d
->glFormat
.blueBufferSize();
1018 if (deviceIsPixmap())
1019 p
->cColorBits
= pmDepth
;
1023 p
->iPixelType
= PFD_TYPE_COLORINDEX
;
1026 if (d
->glFormat
.alpha())
1027 p
->cAlphaBits
= d
->glFormat
.alphaBufferSize() == -1 ? 8 : d
->glFormat
.alphaBufferSize();
1028 if (d
->glFormat
.accum()) {
1029 p
->cAccumRedBits
= p
->cAccumGreenBits
= p
->cAccumBlueBits
= p
->cAccumAlphaBits
=
1030 d
->glFormat
.accumBufferSize() == -1 ? 16 : d
->glFormat
.accumBufferSize();
1032 if (d
->glFormat
.stencil())
1033 p
->cStencilBits
= d
->glFormat
.stencilBufferSize() == -1 ? 8 : d
->glFormat
.stencilBufferSize();
1034 p
->iLayerType
= PFD_MAIN_PLANE
;
1035 chosenPfi
= ChoosePixelFormat(pdc
, p
);
1038 qErrnoWarning("QGLContext: ChoosePixelFormat failed");
1040 // Since the GDI function ChoosePixelFormat() does not handle
1041 // overlay and direct-rendering requests, we must roll our own here
1043 bool doSearch
= chosenPfi
<= 0;
1044 PIXELFORMATDESCRIPTOR pfd
;
1047 DescribePixelFormat(pdc
, chosenPfi
, sizeof(PIXELFORMATDESCRIPTOR
),
1049 fmt
= pfdToQGLFormat(&pfd
);
1050 if (d
->glFormat
.hasOverlay() && !fmt
.hasOverlay())
1052 else if (!qLogEq(d
->glFormat
.directRendering(), fmt
.directRendering()))
1054 else if (deviceIsPixmap() && (!(pfd
.dwFlags
& PFD_DRAW_TO_BITMAP
) ||
1055 pfd
.cColorBits
!= pmDepth
))
1057 else if (!deviceIsPixmap() && !(pfd
.dwFlags
& PFD_DRAW_TO_WINDOW
))
1059 else if (!qLogEq(d
->glFormat
.rgba(), fmt
.rgba()))
1064 int pfiMax
= DescribePixelFormat(pdc
, 0, 0, NULL
);
1067 for (int pfi
= 1; pfi
<= pfiMax
; pfi
++) {
1068 DescribePixelFormat(pdc
, pfi
, sizeof(PIXELFORMATDESCRIPTOR
), &pfd
);
1069 if (!(pfd
.dwFlags
& PFD_SUPPORT_OPENGL
))
1071 if (deviceIsPixmap() && (!(pfd
.dwFlags
& PFD_DRAW_TO_BITMAP
) ||
1072 pfd
.cColorBits
!= pmDepth
))
1074 if (!deviceIsPixmap() && !(pfd
.dwFlags
& PFD_DRAW_TO_WINDOW
))
1077 fmt
= pfdToQGLFormat(&pfd
);
1078 if (d
->glFormat
.hasOverlay() && !fmt
.hasOverlay())
1081 int score
= pfd
.cColorBits
;
1082 if (qLogEq(d
->glFormat
.depth(), fmt
.depth()))
1083 score
+= pfd
.cDepthBits
;
1084 if (qLogEq(d
->glFormat
.alpha(), fmt
.alpha()))
1085 score
+= pfd
.cAlphaBits
;
1086 if (qLogEq(d
->glFormat
.accum(), fmt
.accum()))
1087 score
+= pfd
.cAccumBits
;
1088 if (qLogEq(d
->glFormat
.stencil(), fmt
.stencil()))
1089 score
+= pfd
.cStencilBits
;
1090 if (qLogEq(d
->glFormat
.doubleBuffer(), fmt
.doubleBuffer()))
1092 if (qLogEq(d
->glFormat
.stereo(), fmt
.stereo()))
1094 if (qLogEq(d
->glFormat
.directRendering(), fmt
.directRendering()))
1096 if (qLogEq(d
->glFormat
.rgba(), fmt
.rgba()))
1098 if (score
> bestScore
) {
1105 chosenPfi
= bestPfi
;
1113 void QGLContext::reset()
1116 // workaround for matrox driver:
1117 // make a cheap call to opengl to force loading of DLL
1120 glGetIntegerv(GL_DEPTH_BITS
, ¶ms
);
1129 wglDeleteContext(d
->rc
);
1131 if (d
->win
&& d
->dc
)
1132 ReleaseDC(d
->win
, d
->dc
);
1133 if (deviceIsPixmap()) {
1134 DeleteDC(d
->hbitmap_hdc
);
1135 DeleteObject(d
->hbitmap
);
1141 d
->pixelFormatId
= 0;
1144 d
->transpColor
= QColor();
1147 d
->initDone
= false;
1148 qgl_share_reg()->removeShare(this);
1152 // NOTE: In a multi-threaded environment, each thread has a current
1153 // context. If we want to make this code thread-safe, we probably
1154 // have to use TLS (thread local storage) for keeping current contexts.
1157 void QGLContext::makeCurrent()
1160 if (d
->rc
== wglGetCurrentContext() || !d
->valid
) // already current
1163 d
->dc
= GetDC(d
->win
);
1165 qwglError("QGLContext::makeCurrent()", "GetDC()");
1168 } else if (deviceIsPixmap()) {
1169 d
->dc
= d
->hbitmap_hdc
;
1172 HPALETTE hpal
= QColormap::hPal();
1174 SelectPalette(d
->dc
, hpal
, FALSE
);
1175 RealizePalette(d
->dc
);
1177 if (d
->glFormat
.plane()) {
1178 wglRealizeLayerPalette(d
->dc
, d
->glFormat
.plane(), TRUE
);
1181 if (wglMakeCurrent(d
->dc
, d
->rc
)) {
1182 QGLContextPrivate::setCurrentContext(this);
1184 qwglError("QGLContext::makeCurrent()", "wglMakeCurrent");
1189 void QGLContext::doneCurrent()
1192 wglMakeCurrent(0, 0);
1193 QGLContextPrivate::setCurrentContext(0);
1194 if (deviceIsPixmap() && d
->hbitmap
) {
1195 QPixmap
*pm
= static_cast<QPixmap
*>(d
->paintDevice
);
1196 *pm
= QPixmap::fromWinHBITMAP(d
->hbitmap
);
1198 if (d
->win
&& d
->dc
) {
1199 ReleaseDC(d
->win
, d
->dc
);
1204 void QGLContext::swapBuffers() const
1206 Q_D(const QGLContext
);
1207 if (d
->dc
&& d
->glFormat
.doubleBuffer() && !deviceIsPixmap()) {
1208 if (d
->glFormat
.plane())
1209 wglSwapLayerBuffers(d
->dc
, WGL_SWAP_OVERLAY1
);
1211 if (d
->glFormat
.hasOverlay())
1212 wglSwapLayerBuffers(d
->dc
, WGL_SWAP_MAIN_PLANE
);
1220 QColor
QGLContext::overlayTransparentColor() const
1222 return d_func()->transpColor
;
1226 uint
QGLContext::colorIndex(const QColor
& c
) const
1228 Q_D(const QGLContext
);
1232 int idx
= d
->cmap
->find(c
.rgb());
1235 if (d
->dc
&& d
->glFormat
.plane()) {
1236 idx
= d
->cmap
->allocate(c
.rgb());
1238 COLORREF r
= RGB(qRed(c
.rgb()),qGreen(c
.rgb()),qBlue(c
.rgb()));
1239 wglSetLayerPaletteEntries(d
->dc
, d
->glFormat
.plane(), idx
, 1, &r
);
1240 wglRealizeLayerPalette(d
->dc
, d
->glFormat
.plane(), TRUE
);
1244 return d
->cmap
->findNearest(c
.rgb());
1246 QColormap cmap
= QColormap::instance();
1247 return cmap
.pixel(c
) & 0x00ffffff; // Assumes standard palette
1250 void QGLContext::generateFontDisplayLists(const QFont
& fnt
, int listBase
)
1255 HDC display_dc
= GetDC(0);
1256 HDC tmp_dc
= CreateCompatibleDC(display_dc
);
1257 HGDIOBJ old_font
= SelectObject(tmp_dc
, fnt
.handle());
1259 ReleaseDC(0, display_dc
);
1261 if (!wglUseFontBitmaps(tmp_dc
, 0, 256, listBase
))
1262 qWarning("QGLContext::generateFontDisplayLists: Could not generate display lists for font '%s'", fnt
.family().toLatin1().data());
1264 SelectObject(tmp_dc
, old_font
);
1268 void *QGLContext::getProcAddress(const QString
&proc
) const
1270 return (void *)wglGetProcAddress(proc
.toLatin1());
1273 /*****************************************************************************
1274 QGLWidget Win32/WGL-specific code
1275 *****************************************************************************/
1277 void QGLWidgetPrivate::init(QGLContext
*ctx
, const QGLWidget
* shareWidget
)
1281 initContext(ctx
, shareWidget
);
1283 if (q
->isValid() && q
->context()->format().hasOverlay()) {
1284 olcx
= new QGLContext(QGLFormat::defaultOverlayFormat(), q
);
1285 if (!olcx
->create(shareWidget
? shareWidget
->overlayContext() : 0)) {
1288 glcx
->d_func()->glFormat
.setOverlay(false);
1296 Store color values in the given colormap.
1298 static void qStoreColors(HPALETTE cmap
, const QGLColormap
& cols
)
1303 for (int i
= 0; i
< cols
.size(); i
++) {
1304 color
= cols
.entryRgb(i
);
1305 pe
.peRed
= qRed(color
);
1306 pe
.peGreen
= qGreen(color
);
1307 pe
.peBlue
= qBlue(color
);
1310 SetPaletteEntries(cmap
, i
, 1, &pe
);
1314 void QGLWidgetPrivate::updateColormap()
1319 HDC hdc
= GetDC(q
->winId());
1320 SelectPalette(hdc
, (HPALETTE
) cmap
.handle(), TRUE
);
1321 qStoreColors((HPALETTE
) cmap
.handle(), cmap
);
1322 RealizePalette(hdc
);
1323 ReleaseDC(q
->winId(), hdc
);
1326 void QGLWidget::setMouseTracking(bool enable
)
1328 QWidget::setMouseTracking(enable
);
1332 void QGLWidget::resizeEvent(QResizeEvent
*)
1338 if (!d
->glcx
->initialized())
1340 resizeGL(width(), height());
1342 makeOverlayCurrent();
1343 resizeOverlayGL(width(), height());
1348 const QGLContext
* QGLWidget::overlayContext() const
1350 return d_func()->olcx
;
1354 void QGLWidget::makeOverlayCurrent()
1358 d
->olcx
->makeCurrent();
1359 if (!d
->olcx
->initialized()) {
1360 initializeOverlayGL();
1361 d
->olcx
->setInitialized(true);
1367 void QGLWidget::updateOverlayGL()
1371 makeOverlayCurrent();
1373 if (d
->olcx
->format().doubleBuffer()) {
1375 d
->olcx
->swapBuffers();
1384 void QGLWidget::setContext(QGLContext
*context
,
1385 const QGLContext
* shareContext
,
1386 bool deleteOldContext
)
1390 qWarning("QGLWidget::setContext: Cannot set null context");
1393 if (!context
->deviceIsPixmap() && context
->device() != this) {
1394 qWarning("QGLWidget::setContext: Context must refer to this widget");
1399 d
->glcx
->doneCurrent();
1400 QGLContext
* oldcx
= d
->glcx
;
1403 bool doShow
= false;
1404 if (oldcx
&& oldcx
->d_func()->win
== winId() && !d
->glcx
->deviceIsPixmap()) {
1405 // We already have a context and must therefore create a new
1406 // window since Windows does not permit setting a new OpenGL
1407 // context for a window that already has one set.
1408 doShow
= isVisible();
1409 QWidget
*pW
= static_cast<QWidget
*>(parent());
1410 QPoint pos
= geometry().topLeft();
1411 setParent(pW
, windowFlags());
1415 if (!d
->glcx
->isValid()) {
1416 bool wasSharing
= shareContext
|| (oldcx
&& oldcx
->isSharing());
1417 d
->glcx
->create(shareContext
? shareContext
: oldcx
);
1418 // the above is a trick to keep disp lists etc when a
1419 // QGLWidget has been reparented, so remove the sharing
1420 // flag if we don't actually have a sharing context.
1422 d
->glcx
->d_ptr
->sharing
= false;
1425 if (deleteOldContext
)
1433 bool QGLWidgetPrivate::renderCxPm(QPixmap
*)
1438 void QGLWidgetPrivate::cleanupColormaps()
1441 if (cmap
.handle()) {
1442 HDC hdc
= GetDC(q
->winId());
1443 SelectPalette(hdc
, (HPALETTE
) GetStockObject(DEFAULT_PALETTE
), FALSE
);
1444 DeleteObject((HPALETTE
) cmap
.handle());
1445 ReleaseDC(q
->winId(), hdc
);
1451 const QGLColormap
& QGLWidget::colormap() const
1453 return d_func()->cmap
;
1456 void QGLWidget::setColormap(const QGLColormap
& c
)
1461 if (d
->cmap
.handle()) { // already have an allocated cmap
1462 d
->updateColormap();
1464 LOGPALETTE
*lpal
= (LOGPALETTE
*) malloc(sizeof(LOGPALETTE
)
1465 +c
.size()*sizeof(PALETTEENTRY
));
1466 lpal
->palVersion
= 0x300;
1467 lpal
->palNumEntries
= c
.size();
1468 d
->cmap
.setHandle(CreatePalette(lpal
));
1470 d
->updateColormap();
1474 void QGLExtensions::init()
1476 static bool init_done
= false;
1481 QGLTempContext
temp_ctx(QGLFormat::defaultFormat().directRendering());