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