/src/opengl/qgl_win.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 1601 lines · 1308 code · 192 blank · 101 comment · 311 complexity · 36e676a68b5ad660dbe40719742b6a53 MD5 · raw file

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