1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2013 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup GHOST
22 *
23 * Definition of GHOST_ContextWGL class.
24 */
25
26 #include "GHOST_ContextWGL.h"
27
28 #include <tchar.h>
29
30 #include <cassert>
31 #include <cstdio>
32 #include <vector>
33
34 HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
35 int GHOST_ContextWGL::s_sharedCount = 0;
36
37 /* Some third-generation Intel video-cards are constantly bring problems */
is_crappy_intel_card()38 static bool is_crappy_intel_card()
39 {
40 return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
41 }
42
GHOST_ContextWGL(bool stereoVisual,bool alphaBackground,HWND hWnd,HDC hDC,int contextProfileMask,int contextMajorVersion,int contextMinorVersion,int contextFlags,int contextResetNotificationStrategy)43 GHOST_ContextWGL::GHOST_ContextWGL(bool stereoVisual,
44 bool alphaBackground,
45 HWND hWnd,
46 HDC hDC,
47 int contextProfileMask,
48 int contextMajorVersion,
49 int contextMinorVersion,
50 int contextFlags,
51 int contextResetNotificationStrategy)
52 : GHOST_Context(stereoVisual),
53 m_hWnd(hWnd),
54 m_hDC(hDC),
55 m_contextProfileMask(contextProfileMask),
56 m_contextMajorVersion(contextMajorVersion),
57 m_contextMinorVersion(contextMinorVersion),
58 m_contextFlags(contextFlags),
59 m_alphaBackground(alphaBackground),
60 m_contextResetNotificationStrategy(contextResetNotificationStrategy),
61 m_hGLRC(NULL)
62 #ifndef NDEBUG
63 ,
64 m_dummyVendor(NULL),
65 m_dummyRenderer(NULL),
66 m_dummyVersion(NULL)
67 #endif
68 {
69 assert(m_hDC != NULL);
70 }
71
~GHOST_ContextWGL()72 GHOST_ContextWGL::~GHOST_ContextWGL()
73 {
74 if (m_hGLRC != NULL) {
75 if (m_hGLRC == ::wglGetCurrentContext())
76 WIN32_CHK(::wglMakeCurrent(NULL, NULL));
77
78 if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) {
79 assert(s_sharedCount > 0);
80
81 s_sharedCount--;
82
83 if (s_sharedCount == 0)
84 s_sharedHGLRC = NULL;
85
86 WIN32_CHK(::wglDeleteContext(m_hGLRC));
87 }
88 }
89
90 #ifndef NDEBUG
91 if (m_dummyRenderer) {
92 free((void *)m_dummyRenderer);
93 free((void *)m_dummyVendor);
94 free((void *)m_dummyVersion);
95 }
96 #endif
97 }
98
swapBuffers()99 GHOST_TSuccess GHOST_ContextWGL::swapBuffers()
100 {
101 return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure;
102 }
103
setSwapInterval(int interval)104 GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
105 {
106 if (WGLEW_EXT_swap_control)
107 return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
108 else
109 return GHOST_kFailure;
110 }
111
getSwapInterval(int & intervalOut)112 GHOST_TSuccess GHOST_ContextWGL::getSwapInterval(int &intervalOut)
113 {
114 if (WGLEW_EXT_swap_control) {
115 intervalOut = ::wglGetSwapIntervalEXT();
116 return GHOST_kSuccess;
117 }
118 else {
119 return GHOST_kFailure;
120 }
121 }
122
activateDrawingContext()123 GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
124 {
125 if (WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
126 return GHOST_kSuccess;
127 }
128 else {
129 return GHOST_kFailure;
130 }
131 }
132
releaseDrawingContext()133 GHOST_TSuccess GHOST_ContextWGL::releaseDrawingContext()
134 {
135 if (WIN32_CHK(::wglMakeCurrent(NULL, NULL))) {
136 return GHOST_kSuccess;
137 }
138 else {
139 return GHOST_kFailure;
140 }
141 }
142
143 /* Ron Fosner's code for weighting pixel formats and forcing software.
144 * See http://www.opengl.org/resources/faq/technical/weight.cpp
145 */
weight_pixel_format(PIXELFORMATDESCRIPTOR & pfd,PIXELFORMATDESCRIPTOR & preferredPFD)146 static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR &preferredPFD)
147 {
148 int weight = 0;
149
150 /* assume desktop color depth is 32 bits per pixel */
151
152 /* cull unusable pixel formats */
153 /* if no formats can be found, can we determine why it was rejected? */
154 if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) || !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
155 !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
156 !(pfd.iPixelType == PFD_TYPE_RGBA) ||
157 (pfd.cColorBits > 32) || /* 64 bit formats disable aero */
158 (pfd.dwFlags & PFD_GENERIC_FORMAT)) /* no software renderers */
159 {
160 return 0;
161 }
162
163 weight = 1; /* it's usable */
164
165 weight += pfd.cColorBits - 8;
166
167 if (preferredPFD.cAlphaBits > 0 && pfd.cAlphaBits > 0)
168 weight++;
169 #ifdef WIN32_COMPOSITING
170 if ((preferredPFD.dwFlags & PFD_SUPPORT_COMPOSITION) && (pfd.dwFlags & PFD_SUPPORT_COMPOSITION))
171 weight++;
172 #endif
173
174 return weight;
175 }
176
177 /*
178 * A modification of Ron Fosner's replacement for ChoosePixelFormat
179 * returns 0 on error, else returns the pixel format number to be used
180 */
choose_pixel_format_legacy(HDC hDC,PIXELFORMATDESCRIPTOR & preferredPFD)181 static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
182 {
183 int iPixelFormat = 0;
184 int weight = 0;
185
186 int iStereoPixelFormat = 0;
187 int stereoWeight = 0;
188
189 /* choose a pixel format using the useless Windows function in case we come up empty handed */
190 int iLastResortPixelFormat = ::ChoosePixelFormat(hDC, &preferredPFD);
191
192 WIN32_CHK(iLastResortPixelFormat != 0);
193
194 int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
195
196 WIN32_CHK(lastPFD != 0);
197
198 for (int i = 1; i <= lastPFD; i++) {
199 PIXELFORMATDESCRIPTOR pfd;
200 int check = ::DescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
201
202 WIN32_CHK(check == lastPFD);
203
204 int w = weight_pixel_format(pfd, preferredPFD);
205
206 if (w > weight) {
207 weight = w;
208 iPixelFormat = i;
209 }
210
211 if (w > stereoWeight && (preferredPFD.dwFlags & pfd.dwFlags & PFD_STEREO)) {
212 stereoWeight = w;
213 iStereoPixelFormat = i;
214 }
215 }
216
217 /* choose any available stereo format over a non-stereo format */
218 if (iStereoPixelFormat != 0)
219 iPixelFormat = iStereoPixelFormat;
220
221 if (iPixelFormat == 0) {
222 fprintf(stderr, "Warning! Using result of ChoosePixelFormat.\n");
223 iPixelFormat = iLastResortPixelFormat;
224 }
225
226 return iPixelFormat;
227 }
228
229 /**
230 * Clone a window for the purpose of creating a temporary context to initialize WGL extensions.
231 * There is no generic way to clone the lpParam parameter,
232 * so the caller is responsible for cloning it themselves.
233 */
clone_window(HWND hWnd,LPVOID lpParam)234 static HWND clone_window(HWND hWnd, LPVOID lpParam)
235 {
236 int count;
237
238 SetLastError(NO_ERROR);
239
240 DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
241 WIN32_CHK(GetLastError() == NO_ERROR);
242
243 WCHAR lpClassName[100] = L"";
244 count = GetClassNameW(hWnd, lpClassName, sizeof(lpClassName));
245 WIN32_CHK(count != 0);
246
247 WCHAR lpWindowName[100] = L"";
248 count = GetWindowTextW(hWnd, lpWindowName, sizeof(lpWindowName));
249 WIN32_CHK(count != 0);
250
251 DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
252 WIN32_CHK(GetLastError() == NO_ERROR);
253
254 RECT rect;
255 GetWindowRect(hWnd, &rect);
256 WIN32_CHK(GetLastError() == NO_ERROR);
257
258 HWND hWndParent = (HWND)GetWindowLongPtr(hWnd, GWLP_HWNDPARENT);
259 WIN32_CHK(GetLastError() == NO_ERROR);
260
261 HMENU hMenu = GetMenu(hWnd);
262 WIN32_CHK(GetLastError() == NO_ERROR);
263
264 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
265 WIN32_CHK(GetLastError() == NO_ERROR);
266
267 HWND hwndCloned = CreateWindowExW(dwExStyle,
268 lpClassName,
269 lpWindowName,
270 dwStyle,
271 rect.left,
272 rect.top,
273 rect.right - rect.left,
274 rect.bottom - rect.top,
275 hWndParent,
276 hMenu,
277 hInstance,
278 lpParam);
279
280 WIN32_CHK(hwndCloned != NULL);
281
282 return hwndCloned;
283 }
284
initContextWGLEW(PIXELFORMATDESCRIPTOR & preferredPFD)285 void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
286 {
287 HWND dummyHWND = NULL;
288
289 HDC dummyHDC = NULL;
290 HGLRC dummyHGLRC = NULL;
291
292 HDC prevHDC;
293 HGLRC prevHGLRC;
294
295 int iPixelFormat;
296
297 SetLastError(NO_ERROR);
298
299 prevHDC = ::wglGetCurrentDC();
300 WIN32_CHK(GetLastError() == NO_ERROR);
301
302 prevHGLRC = ::wglGetCurrentContext();
303 WIN32_CHK(GetLastError() == NO_ERROR);
304
305 iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
306
307 if (iPixelFormat == 0)
308 goto finalize;
309
310 PIXELFORMATDESCRIPTOR chosenPFD;
311 if (!WIN32_CHK(
312 ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
313 goto finalize;
314
315 if (m_hWnd) {
316 dummyHWND = clone_window(m_hWnd, NULL);
317
318 if (dummyHWND == NULL)
319 goto finalize;
320
321 dummyHDC = GetDC(dummyHWND);
322 }
323
324 if (!WIN32_CHK(dummyHDC != NULL))
325 goto finalize;
326
327 if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD)))
328 goto finalize;
329
330 dummyHGLRC = ::wglCreateContext(dummyHDC);
331
332 if (!WIN32_CHK(dummyHGLRC != NULL))
333 goto finalize;
334
335 if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
336 goto finalize;
337
338 if (GLEW_CHK(glewInit()) != GLEW_OK)
339 fprintf(stderr, "Warning! Dummy GLEW/WGLEW failed to initialize properly.\n");
340
341 // the following are not technially WGLEW, but they also require a context to work
342
343 #ifndef NDEBUG
344 free((void *)m_dummyRenderer);
345 free((void *)m_dummyVendor);
346 free((void *)m_dummyVersion);
347
348 m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
349 m_dummyVendor = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
350 m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
351 #endif
352
353 finalize:
354 WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
355
356 if (dummyHGLRC != NULL)
357 WIN32_CHK(::wglDeleteContext(dummyHGLRC));
358
359 if (dummyHWND != NULL) {
360 if (dummyHDC != NULL)
361 WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
362
363 WIN32_CHK(::DestroyWindow(dummyHWND));
364 }
365 }
366
makeAttribList(std::vector<int> & out,bool stereoVisual,bool needAlpha)367 static void makeAttribList(std::vector<int> &out, bool stereoVisual, bool needAlpha)
368 {
369 out.clear();
370 out.reserve(30);
371
372 out.push_back(WGL_SUPPORT_OPENGL_ARB);
373 out.push_back(GL_TRUE);
374
375 out.push_back(WGL_DRAW_TO_WINDOW_ARB);
376 out.push_back(GL_TRUE);
377
378 out.push_back(WGL_DOUBLE_BUFFER_ARB);
379 out.push_back(GL_TRUE);
380
381 out.push_back(WGL_ACCELERATION_ARB);
382 out.push_back(WGL_FULL_ACCELERATION_ARB);
383
384 if (stereoVisual) {
385 out.push_back(WGL_STEREO_ARB);
386 out.push_back(GL_TRUE);
387 }
388
389 out.push_back(WGL_PIXEL_TYPE_ARB);
390 out.push_back(WGL_TYPE_RGBA_ARB);
391
392 out.push_back(WGL_COLOR_BITS_ARB);
393 out.push_back(24);
394
395 if (needAlpha) {
396 out.push_back(WGL_ALPHA_BITS_ARB);
397 out.push_back(8);
398 }
399
400 out.push_back(0);
401 }
402
_choose_pixel_format_arb_1(bool stereoVisual,bool needAlpha)403 int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual, bool needAlpha)
404 {
405 std::vector<int> iAttributes;
406
407 #define _MAX_PIXEL_FORMATS 32
408
409 int iPixelFormat = 0;
410 int iPixelFormats[_MAX_PIXEL_FORMATS];
411
412 makeAttribList(iAttributes, stereoVisual, needAlpha);
413
414 UINT nNumFormats;
415 WIN32_CHK(wglChoosePixelFormatARB(
416 m_hDC, &(iAttributes[0]), NULL, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
417
418 if (nNumFormats > 0) {
419 iPixelFormat = iPixelFormats[0];
420
421 #ifdef WIN32_COMPOSITING
422 if (needAlpha) {
423 // scan through all pixel format to make sure one supports compositing
424 PIXELFORMATDESCRIPTOR pfd;
425 int i;
426
427 for (i = 0; i < nNumFormats; i++) {
428 if (DescribePixelFormat(m_hDC, iPixelFormats[i], sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
429 if (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) {
430 iPixelFormat = iPixelFormats[i];
431 break;
432 }
433 }
434 }
435 if (i == nNumFormats) {
436 fprintf(stderr, "Warning! Unable to find a pixel format with compositing capability.\n");
437 }
438 }
439 #endif
440 }
441
442 // check pixel format
443 if (iPixelFormat != 0) {
444 if (needAlpha) {
445 int alphaBits, iQuery = WGL_ALPHA_BITS_ARB;
446 wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, &iQuery, &alphaBits);
447 if (alphaBits == 0) {
448 fprintf(stderr, "Warning! Unable to find a frame buffer with alpha channel.\n");
449 }
450 }
451 }
452 return iPixelFormat;
453 }
454
choose_pixel_format_arb(bool stereoVisual,bool needAlpha)455 int GHOST_ContextWGL::choose_pixel_format_arb(bool stereoVisual, bool needAlpha)
456 {
457 int iPixelFormat;
458
459 iPixelFormat = _choose_pixel_format_arb_1(stereoVisual, needAlpha);
460
461 if (iPixelFormat == 0 && stereoVisual) {
462 fprintf(stderr, "Warning! Unable to find a stereo pixel format.\n");
463
464 iPixelFormat = _choose_pixel_format_arb_1(false, needAlpha);
465
466 m_stereoVisual = false; // set context property to actual value
467 }
468
469 return iPixelFormat;
470 }
471
choose_pixel_format(bool stereoVisual,bool needAlpha)472 int GHOST_ContextWGL::choose_pixel_format(bool stereoVisual, bool needAlpha)
473 {
474 PIXELFORMATDESCRIPTOR preferredPFD = {
475 sizeof(PIXELFORMATDESCRIPTOR), /* size */
476 1, /* version */
477 (DWORD)(
478 PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW |
479 PFD_DOUBLEBUFFER | /* support double-buffering */
480 (stereoVisual ? PFD_STEREO : 0) | /* support stereo */
481 (
482 #ifdef WIN32_COMPOSITING
483 needAlpha ?
484 PFD_SUPPORT_COMPOSITION : /* support composition for transparent background */
485 #endif
486 0)),
487 PFD_TYPE_RGBA, /* color type */
488 (BYTE)(needAlpha ? 32 : 24), /* preferred color depth */
489 0,
490 0,
491 0,
492 0,
493 0,
494 0, /* color bits (ignored) */
495 (BYTE)(needAlpha ? 8 : 0), /* alpha buffer */
496 0, /* alpha shift (ignored) */
497 0, /* no accumulation buffer */
498 0,
499 0,
500 0,
501 0, /* accum bits (ignored) */
502 0, /* depth buffer */
503 0, /* stencil buffer */
504 0, /* no auxiliary buffers */
505 PFD_MAIN_PLANE, /* main layer */
506 0, /* reserved */
507 0,
508 0,
509 0 /* layer, visible, and damage masks (ignored) */
510 };
511
512 initContextWGLEW(preferredPFD);
513
514 int iPixelFormat = 0;
515
516 if (WGLEW_ARB_pixel_format)
517 iPixelFormat = choose_pixel_format_arb(stereoVisual, needAlpha);
518
519 if (iPixelFormat == 0)
520 iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
521
522 return iPixelFormat;
523 }
524
525 #ifndef NDEBUG
reportContextString(const char * name,const char * dummy,const char * context)526 static void reportContextString(const char *name, const char *dummy, const char *context)
527 {
528 fprintf(stderr, "%s: %s\n", name, context);
529
530 if (dummy && strcmp(dummy, context) != 0)
531 fprintf(stderr, "Warning! Dummy %s: %s\n", name, dummy);
532 }
533 #endif
534
initializeDrawingContext()535 GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
536 {
537 SetLastError(NO_ERROR);
538
539 HGLRC prevHGLRC = ::wglGetCurrentContext();
540 WIN32_CHK(GetLastError() == NO_ERROR);
541
542 HDC prevHDC = ::wglGetCurrentDC();
543 WIN32_CHK(GetLastError() == NO_ERROR);
544
545 if (!WGLEW_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) {
546 const bool needAlpha = m_alphaBackground;
547 int iPixelFormat;
548 int lastPFD;
549
550 PIXELFORMATDESCRIPTOR chosenPFD;
551
552 iPixelFormat = choose_pixel_format(m_stereoVisual, needAlpha);
553
554 if (iPixelFormat == 0) {
555 goto error;
556 }
557
558 lastPFD = ::DescribePixelFormat(
559 m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
560
561 if (!WIN32_CHK(lastPFD != 0)) {
562 goto error;
563 }
564
565 if (needAlpha && chosenPFD.cAlphaBits == 0)
566 fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
567
568 if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
569 goto error;
570 }
571 }
572
573 if (WGLEW_ARB_create_context) {
574 int profileBitCore = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
575 int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
576
577 #ifdef WITH_GLEW_ES
578 int profileBitES = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
579 #endif
580
581 if (!WGLEW_ARB_create_context_profile && profileBitCore)
582 fprintf(stderr, "Warning! OpenGL core profile not available.\n");
583
584 if (!WGLEW_ARB_create_context_profile && profileBitCompat)
585 fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
586
587 #ifdef WITH_GLEW_ES
588 if (!WGLEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
589 fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
590
591 if (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
592 fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
593 #endif
594
595 int profileMask = 0;
596
597 if (WGLEW_ARB_create_context_profile && profileBitCore)
598 profileMask |= profileBitCore;
599
600 if (WGLEW_ARB_create_context_profile && profileBitCompat)
601 profileMask |= profileBitCompat;
602
603 #ifdef WITH_GLEW_ES
604 if (WGLEW_EXT_create_context_es_profile && profileBitES)
605 profileMask |= profileBitES;
606 #endif
607
608 if (profileMask != m_contextProfileMask)
609 fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
610
611 std::vector<int> iAttributes;
612
613 if (profileMask) {
614 iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
615 iAttributes.push_back(profileMask);
616 }
617
618 if (m_contextMajorVersion != 0) {
619 iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
620 iAttributes.push_back(m_contextMajorVersion);
621 }
622
623 if (m_contextMinorVersion != 0) {
624 iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
625 iAttributes.push_back(m_contextMinorVersion);
626 }
627
628 if (m_contextFlags != 0) {
629 iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
630 iAttributes.push_back(m_contextFlags);
631 }
632
633 if (m_contextResetNotificationStrategy != 0) {
634 if (WGLEW_ARB_create_context_robustness) {
635 iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
636 iAttributes.push_back(m_contextResetNotificationStrategy);
637 }
638 else {
639 fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
640 }
641 }
642
643 iAttributes.push_back(0);
644
645 m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
646 }
647
648 /* Silence warnings interpreted as errors by users when trying to get
649 * a context with version higher than 3.3 Core. */
650 {
651 const bool silent = m_contextMajorVersion > 3;
652 if (!WIN32_CHK_SILENT(m_hGLRC != NULL, silent)) {
653 goto error;
654 }
655 }
656
657 s_sharedCount++;
658
659 if (s_sharedHGLRC == NULL) {
660 s_sharedHGLRC = m_hGLRC;
661 }
662 else if (!WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
663 goto error;
664 }
665
666 if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
667 goto error;
668 }
669
670 initContextGLEW();
671
672 if (is_crappy_intel_card()) {
673 /* Some Intel cards with context 4.1 or 4.2
674 * don't have the point sprite enabled by default.
675 *
676 * However GL_POINT_SPRITE was removed in 3.2 and is now permanently ON.
677 * Then use brute force. */
678 glEnable(GL_POINT_SPRITE);
679 }
680
681 initClearGL();
682 ::SwapBuffers(m_hDC);
683
684 #ifndef NDEBUG
685 {
686 const char *vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
687 const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
688 const char *version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
689
690 reportContextString("Vendor", m_dummyVendor, vendor);
691 reportContextString("Renderer", m_dummyRenderer, renderer);
692 reportContextString("Version", m_dummyVersion, version);
693
694 fprintf(stderr, "Context Version: %d.%d\n", m_contextMajorVersion, m_contextMinorVersion);
695 }
696 #endif
697
698 return GHOST_kSuccess;
699 error:
700 ::wglMakeCurrent(prevHDC, prevHGLRC);
701 return GHOST_kFailure;
702 }
703
releaseNativeHandles()704 GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
705 {
706 GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess :
707 GHOST_kFailure;
708
709 m_hWnd = NULL;
710 m_hDC = NULL;
711
712 return success;
713 }
714