BGE: alpha on frame buffer and precedence of MSAA over swap.
[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 #ifdef WITH_GLEW_MX
44 WGLEWContext *wglewContext = NULL;
45 #endif
46
47 HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
48 int   GHOST_ContextWGL::s_sharedCount = 0;
49
50 bool GHOST_ContextWGL::s_singleContextMode = false;
51
52
53 /* Intel video-cards don't work fine with multiple contexts and
54  * have to share the same context for all windows.
55  * But if we just share context for all windows it could work incorrect
56  * with multiple videocards configuration. Suppose, that Intel videocards
57  * can't be in multiple-devices configuration. */
58 static bool is_crappy_intel_card()
59 {
60         return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
61 }
62
63
64 GHOST_ContextWGL::GHOST_ContextWGL(
65         bool stereoVisual,
66                 bool alphaBackground,
67         GHOST_TUns16 numOfAASamples,
68         HWND hWnd,
69         HDC hDC,
70         int contextProfileMask,
71         int contextMajorVersion,
72         int contextMinorVersion,
73         int contextFlags,
74         int contextResetNotificationStrategy)
75     : GHOST_Context(stereoVisual, numOfAASamples),
76       m_hWnd(hWnd),
77       m_hDC(hDC),
78       m_contextProfileMask(contextProfileMask),
79       m_contextMajorVersion(contextMajorVersion),
80       m_contextMinorVersion(contextMinorVersion),
81       m_contextFlags(contextFlags),
82           m_alphaBackground(alphaBackground),
83       m_contextResetNotificationStrategy(contextResetNotificationStrategy),
84       m_hGLRC(NULL)
85 #ifdef WITH_GLEW_MX
86       ,
87       m_wglewContext(NULL)
88 #endif
89 #ifndef NDEBUG
90       ,
91       m_dummyVendor(NULL),
92       m_dummyRenderer(NULL),
93       m_dummyVersion(NULL)
94 #endif
95 {
96         assert(m_hWnd);
97         assert(m_hDC);
98 }
99
100
101 GHOST_ContextWGL::~GHOST_ContextWGL()
102 {
103         if (m_hGLRC != NULL) {
104                 if (m_hGLRC == ::wglGetCurrentContext())
105                         WIN32_CHK(::wglMakeCurrent(NULL, NULL));
106
107                 if (m_hGLRC != s_sharedHGLRC || s_sharedCount == 1) {
108                         assert(s_sharedCount > 0);
109
110                         s_sharedCount--;
111
112                         if (s_sharedCount == 0)
113                                 s_sharedHGLRC = NULL;
114
115                         WIN32_CHK(::wglDeleteContext(m_hGLRC));
116                 }
117         }
118
119 #ifdef WITH_GLEW_MX
120         delete m_wglewContext;
121 #endif
122
123 #ifndef NDEBUG
124         free((void*)m_dummyRenderer);
125         free((void*)m_dummyVendor);
126         free((void*)m_dummyVersion);
127 #endif
128 }
129
130
131 GHOST_TSuccess GHOST_ContextWGL::swapBuffers()
132 {
133         return WIN32_CHK(::SwapBuffers(m_hDC)) ? GHOST_kSuccess : GHOST_kFailure;
134 }
135
136
137 GHOST_TSuccess GHOST_ContextWGL::setSwapInterval(int interval)
138 {
139         if (WGLEW_EXT_swap_control)
140                 return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
141         else
142                 return GHOST_kFailure;
143 }
144
145
146 GHOST_TSuccess GHOST_ContextWGL::getSwapInterval(int &intervalOut)
147 {
148         if (WGLEW_EXT_swap_control) {
149                 intervalOut = ::wglGetSwapIntervalEXT();
150                 return GHOST_kSuccess;
151         }
152         else {
153                 return GHOST_kFailure;
154         }
155 }
156
157
158 GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
159 {
160         if (WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
161                 activateGLEW();
162                 return GHOST_kSuccess;
163         }
164         else {
165                 return GHOST_kFailure;
166         }
167 }
168
169
170 /* Ron Fosner's code for weighting pixel formats and forcing software.
171  * See http://www.opengl.org/resources/faq/technical/weight.cpp
172  */
173 static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR &preferredPFD)
174 {
175         int weight = 0;
176
177         /* assume desktop color depth is 32 bits per pixel */
178
179         /* cull unusable pixel formats */
180         /* if no formats can be found, can we determine why it was rejected? */
181         if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)  ||
182             !(pfd.dwFlags & PFD_DRAW_TO_WINDOW)  ||
183             !(pfd.dwFlags & PFD_DOUBLEBUFFER)    || /* Blender _needs_ this */
184             !(pfd.iPixelType == PFD_TYPE_RGBA)   ||
185              (pfd.cDepthBits < 16)               ||
186              (pfd.dwFlags & PFD_GENERIC_FORMAT))    /* no software renderers */
187         {
188                 return 0;
189         }
190
191         weight = 1;  /* it's usable */
192
193         /* the bigger the depth buffer the better */
194         /* give no weight to a 16-bit depth buffer, because those are crap */
195         weight += pfd.cDepthBits - 16;
196
197         weight += pfd.cColorBits -  8;
198
199         if (preferredPFD.cAlphaBits > 0 && pfd.cAlphaBits > 0)
200                 weight++;
201 #ifdef WIN32_COMPOSITING
202         if ((preferredPFD.dwFlags & PFD_SUPPORT_COMPOSITION) && (pfd.dwFlags & PFD_SUPPORT_COMPOSITION))
203                 weight++;
204 #endif
205 #ifdef GHOST_OPENGL_STENCIL
206         if (pfd.cStencilBits >= 8)
207                 weight++;
208 #endif
209
210         /* want swap copy capability -- it matters a lot */
211         if (pfd.dwFlags & PFD_SWAP_COPY)
212                 weight += 16;
213
214         return weight;
215 }
216
217
218 /*
219  * A modification of Ron Fosner's replacement for ChoosePixelFormat
220  * returns 0 on error, else returns the pixel format number to be used
221  */
222 static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
223 {
224         int iPixelFormat = 0;
225         int weight = 0;
226
227         int iStereoPixelFormat = 0;
228         int stereoWeight = 0;
229
230         /* choose a pixel format using the useless Windows function in case we come up empty handed */
231         int iLastResortPixelFormat = ::ChoosePixelFormat(hDC, &preferredPFD);
232
233         WIN32_CHK(iLastResortPixelFormat != 0);
234
235         int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
236
237         WIN32_CHK(lastPFD != 0);
238
239         for (int i = 1; i <= lastPFD; i++) {
240                 PIXELFORMATDESCRIPTOR pfd;
241                 int check = ::DescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
242
243                 WIN32_CHK(check == lastPFD);
244
245                 int w = weight_pixel_format(pfd, preferredPFD);
246
247                 if (w > weight) {
248                         weight = w;
249                         iPixelFormat = i;
250                 }
251
252                 if (w > stereoWeight && (preferredPFD.dwFlags & pfd.dwFlags & PFD_STEREO)) {
253                         stereoWeight = w;
254                         iStereoPixelFormat = i;
255                 }
256         }
257
258         /* choose any available stereo format over a non-stereo format */
259         if (iStereoPixelFormat != 0)
260                 iPixelFormat = iStereoPixelFormat;
261
262         if (iPixelFormat == 0) {
263                 fprintf(stderr, "Warning! Using result of ChoosePixelFormat.\n");
264                 iPixelFormat = iLastResortPixelFormat;
265         }
266
267         return iPixelFormat;
268 }
269
270
271 /*
272  * Clone a window for the purpose of creating a temporary context to initialize WGL extensions.
273  * There is no generic way to clone the lpParam parameter, so the caller is responsible for cloning it themselves.
274  */
275
276 static HWND clone_window(HWND hWnd, LPVOID lpParam)
277 {
278         int count;
279
280         SetLastError(NO_ERROR);
281
282         DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
283         WIN32_CHK(GetLastError() == NO_ERROR);
284
285         WCHAR lpClassName[100] = L"";
286         count = GetClassNameW(hWnd, lpClassName, sizeof(lpClassName));
287         WIN32_CHK(count != 0);
288
289         WCHAR lpWindowName[100] = L"";
290         count = GetWindowTextW(hWnd, lpWindowName, sizeof(lpWindowName));
291         WIN32_CHK(count != 0);
292
293         DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
294         WIN32_CHK(GetLastError() == NO_ERROR);
295
296         RECT rect;
297         GetWindowRect(hWnd, &rect);
298         WIN32_CHK(GetLastError() == NO_ERROR);
299
300         HWND hWndParent = (HWND)GetWindowLongPtr(hWnd, GWLP_HWNDPARENT);
301         WIN32_CHK(GetLastError() == NO_ERROR);
302
303         HMENU hMenu = GetMenu(hWnd);
304         WIN32_CHK(GetLastError() == NO_ERROR);
305
306         HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
307         WIN32_CHK(GetLastError() == NO_ERROR);
308
309         HWND hwndCloned = CreateWindowExW(
310                 dwExStyle,
311                 lpClassName,
312                 lpWindowName,
313                 dwStyle,
314                 rect.left,
315                 rect.top,
316                 rect.right - rect.left,
317                 rect.bottom - rect.top,
318                 hWndParent,
319                 hMenu,
320                 hInstance,
321                 lpParam);
322
323         WIN32_CHK(hwndCloned != NULL);
324
325         return hwndCloned;
326 }
327
328
329 void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
330 {
331         HWND  dummyHWND  = NULL;
332         HDC   dummyHDC   = NULL;
333         HGLRC dummyHGLRC = NULL;
334
335         HDC   prevHDC;
336         HGLRC prevHGLRC;
337
338         int iPixelFormat;
339
340
341 #ifdef WITH_GLEW_MX
342         wglewContext = new WGLEWContext;
343         memset(wglewContext, 0, sizeof(WGLEWContext));
344
345         delete m_wglewContext;
346         m_wglewContext = wglewContext;
347 #endif
348
349         SetLastError(NO_ERROR);
350
351         prevHDC = ::wglGetCurrentDC();
352         WIN32_CHK(GetLastError() == NO_ERROR);
353
354         prevHGLRC = ::wglGetCurrentContext();
355         WIN32_CHK(GetLastError() == NO_ERROR);
356
357         dummyHWND = clone_window(m_hWnd, NULL);
358
359         if (dummyHWND == NULL)
360                 goto finalize;
361
362         dummyHDC = GetDC(dummyHWND);
363
364         if (!WIN32_CHK(dummyHDC != NULL))
365                 goto finalize;
366
367         iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD);
368
369         if (iPixelFormat == 0)
370                 goto finalize;
371
372         PIXELFORMATDESCRIPTOR chosenPFD;
373         if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
374                 goto finalize;
375
376         if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD)))
377                 goto finalize;
378
379         dummyHGLRC = ::wglCreateContext(dummyHDC);
380
381         if (!WIN32_CHK(dummyHGLRC != NULL))
382                 goto finalize;
383
384         if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC)))
385                 goto finalize;
386
387 #ifdef WITH_GLEW_MX
388         if (GLEW_CHK(wglewInit()) != GLEW_OK)
389                 fprintf(stderr, "Warning! WGLEW failed to initialize properly.\n");
390 #else
391         if (GLEW_CHK(glewInit()) != GLEW_OK)
392                 fprintf(stderr, "Warning! Dummy GLEW/WGLEW failed to initialize properly.\n");
393 #endif
394
395         // the following are not technially WGLEW, but they also require a context to work
396
397 #ifndef NDEBUG
398         free((void*)m_dummyRenderer);
399         free((void*)m_dummyVendor);
400         free((void*)m_dummyVersion);
401
402         m_dummyRenderer = _strdup(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
403         m_dummyVendor   = _strdup(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
404         m_dummyVersion  = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
405 #endif
406
407         s_singleContextMode = is_crappy_intel_card();
408
409 finalize:
410         WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
411
412         if (dummyHGLRC != NULL)
413                 WIN32_CHK(::wglDeleteContext(dummyHGLRC));
414
415         if (dummyHWND != NULL) {
416                 if (dummyHDC != NULL)
417                         WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
418
419                 WIN32_CHK(::DestroyWindow(dummyHWND));
420         }
421 }
422
423
424 static void makeAttribList(
425         std::vector<int>& out,
426         bool stereoVisual,
427         int numOfAASamples,
428         int swapMethod,
429         bool needAlpha,
430         bool needStencil,
431         bool sRGB)
432 {
433         out.clear();
434         out.reserve(30);
435
436         out.push_back(WGL_SUPPORT_OPENGL_ARB);
437         out.push_back(GL_TRUE);
438
439         out.push_back(WGL_DRAW_TO_WINDOW_ARB);
440         out.push_back(GL_TRUE);
441
442         out.push_back(WGL_DOUBLE_BUFFER_ARB);
443         out.push_back(GL_TRUE);
444
445         out.push_back(WGL_ACCELERATION_ARB);
446         out.push_back(WGL_FULL_ACCELERATION_ARB);
447
448         out.push_back(WGL_SWAP_METHOD_ARB);
449         out.push_back(swapMethod);
450
451         if (stereoVisual) {
452                 out.push_back(WGL_STEREO_ARB);
453                 out.push_back(GL_TRUE);
454         }
455
456         out.push_back(WGL_PIXEL_TYPE_ARB);
457         out.push_back(WGL_TYPE_RGBA_ARB);
458
459         out.push_back(WGL_COLOR_BITS_ARB);
460         out.push_back(24);
461
462         out.push_back(WGL_DEPTH_BITS_ARB);
463         out.push_back(24);
464
465         if (needAlpha) {
466                 out.push_back(WGL_ALPHA_BITS_ARB);
467                 out.push_back(8);
468         }
469
470         if (needStencil) {
471                 out.push_back(WGL_STENCIL_BITS_ARB);
472                 out.push_back(8);
473         }
474
475         if (numOfAASamples > 0) {
476                 out.push_back(WGL_SAMPLES_ARB);
477                 out.push_back(numOfAASamples);
478
479                 out.push_back(WGL_SAMPLE_BUFFERS_ARB);
480                 out.push_back(GL_TRUE);
481         }
482
483         if (sRGB) {
484                 out.push_back(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
485                 out.push_back(GL_TRUE);
486         }
487
488         out.push_back(0);
489 }
490
491
492 int GHOST_ContextWGL::_choose_pixel_format_arb_2(
493         bool stereoVisual,
494         int *numOfAASamples,
495         bool needAlpha,
496         bool needStencil,
497         bool sRGB,
498         int swapMethod)
499 {
500         std::vector<int> iAttributes;
501
502 #define _MAX_PIXEL_FORMATS 32
503
504         int iPixelFormat = 0;
505         int iPixelFormats[_MAX_PIXEL_FORMATS];
506
507         int samples;
508
509         // guard against some insanely high number of samples
510         if (*numOfAASamples > 64) {
511                 fprintf(stderr, "Warning! Clamping number of samples to 64.\n");
512                 samples = 64;
513         }
514         else {
515                 samples = *numOfAASamples;
516         }
517
518         // request a format with as many samples as possible, but not more than requested
519         while (samples >= 0) {
520                 makeAttribList(
521                         iAttributes,
522                         stereoVisual,
523                         samples,
524                         swapMethod,
525                         needAlpha,
526                         needStencil,
527                         sRGB);
528
529                 UINT nNumFormats;
530                 WIN32_CHK(wglChoosePixelFormatARB(m_hDC, &(iAttributes[0]), NULL, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
531
532 #ifdef WIN32_COMPOSITING
533                 if (needAlpha && nNumFormats) {
534                         // scan through all pixel format to make sure one supports compositing
535                         PIXELFORMATDESCRIPTOR pfd;
536                         int i;
537
538                         for (i = 0; i < nNumFormats; i++) {
539                                 if (DescribePixelFormat(m_hDC, iPixelFormats[i], sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
540                                         if (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) {
541                                                 iPixelFormat = iPixelFormats[i];
542                                                 break;
543                                         }
544                                 }
545                         }
546                         if (i == nNumFormats) {
547                                 fprintf(stderr,
548                                                 "Warning! Unable to find a pixel format with compositing capability.\n");
549                                 iPixelFormat = iPixelFormats[0];
550                         }
551                 }
552                 else
553 #endif
554                         iPixelFormat = iPixelFormats[0];
555                 /* total number of formats that match (regardless of size of iPixelFormat array)
556                  * see: WGL_ARB_pixel_format extension spec */
557                 if (nNumFormats > 0)
558                         break;
559
560                 /* if not reset, then the state of iPixelFormat is undefined after call to wglChoosePixelFormatARB
561                  * see: WGL_ARB_pixel_format extension spec */
562                 iPixelFormat = 0;
563
564                 samples--;
565         }
566
567         // check how many samples were actually gotten
568         if (iPixelFormat != 0) {
569                 int iQuery[] = { WGL_SAMPLES_ARB };
570                 int actualSamples, alphaBits;
571                 wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &actualSamples);
572
573                 if (actualSamples != *numOfAASamples) {
574                         fprintf(stderr,
575                                 "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
576                                 "Substituting one that uses %d samples.\n",
577                                 *numOfAASamples, actualSamples);
578
579                         *numOfAASamples = actualSamples; // set context property to actual value
580                 }
581                 if (needAlpha) {
582                         iQuery[0] = WGL_ALPHA_BITS_ARB;
583                         wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &alphaBits);
584                         if (alphaBits == 0) {
585                                 fprintf(stderr,
586                                                 "Warning! Unable to find a frame buffer with alpha channel.\n");
587                         }
588                 }
589         }
590         else {
591                 *numOfAASamples = 0;
592         }
593         return iPixelFormat;
594 }
595
596
597 int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual,
598         int numOfAASamples,
599         bool needAlpha,
600         bool needStencil,
601         bool sRGB,
602         int *swapMethodOut)
603 {
604         int iPixelFormat;
605         int copyPixelFormat = 0;
606         int undefPixelFormat = 0;
607         int exchPixelFormat = 0;
608         int copyNumOfAASamples = 0;
609         int undefNumOfAASamples = 0;
610         int exchNumOfAASamples = 0;
611
612         *swapMethodOut = WGL_SWAP_COPY_ARB;
613         copyNumOfAASamples = numOfAASamples;
614         copyPixelFormat  = _choose_pixel_format_arb_2(
615                 stereoVisual, &copyNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
616
617         if (copyPixelFormat == 0 || copyNumOfAASamples < numOfAASamples) {
618                 *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
619                 undefNumOfAASamples = numOfAASamples;
620                 undefPixelFormat = _choose_pixel_format_arb_2(
621                         stereoVisual, &undefNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
622
623                 if (undefPixelFormat == 0 || undefNumOfAASamples < numOfAASamples) {
624                         *swapMethodOut = WGL_SWAP_EXCHANGE_ARB;
625                         exchNumOfAASamples = numOfAASamples;
626                         exchPixelFormat = _choose_pixel_format_arb_2(
627                                 stereoVisual, &exchNumOfAASamples, needAlpha, needStencil, sRGB, *swapMethodOut);
628                         if (exchPixelFormat == 0 || exchNumOfAASamples < numOfAASamples) {
629                                 // the number of AA samples cannot be met, take the highest
630                                 if (undefPixelFormat != 0 && undefNumOfAASamples >= exchNumOfAASamples) {
631                                         exchNumOfAASamples = undefNumOfAASamples;
632                                         exchPixelFormat = undefPixelFormat;
633                                         *swapMethodOut = WGL_SWAP_UNDEFINED_ARB;
634                                 }
635                                 if (copyPixelFormat != 0 && copyNumOfAASamples >= exchNumOfAASamples) {
636                                         exchNumOfAASamples = copyNumOfAASamples;
637                                         exchPixelFormat = copyPixelFormat;
638                                         *swapMethodOut = WGL_SWAP_COPY_ARB;
639                                 }
640                         }
641                         iPixelFormat = exchPixelFormat;
642                         m_numOfAASamples = exchNumOfAASamples;
643                 }
644                 else {
645                         iPixelFormat = undefPixelFormat;
646                         m_numOfAASamples = undefNumOfAASamples;
647                 }
648         }
649         else {
650                 iPixelFormat = copyPixelFormat;
651                 m_numOfAASamples = copyNumOfAASamples;
652         }
653         return iPixelFormat;
654 }
655
656
657 int GHOST_ContextWGL::choose_pixel_format_arb(
658         bool stereoVisual,
659         int numOfAASamples,
660         bool needAlpha,
661         bool needStencil,
662         bool sRGB)
663 {
664         int iPixelFormat;
665         int swapMethodOut;
666
667         iPixelFormat = _choose_pixel_format_arb_1(
668                 stereoVisual,
669                 numOfAASamples,
670                 needAlpha,
671                 needStencil,
672                 sRGB,
673                 &swapMethodOut);
674
675         if (iPixelFormat == 0 && stereoVisual) {
676                 fprintf(stderr, "Warning! Unable to find a stereo pixel format.\n");
677
678                 iPixelFormat = _choose_pixel_format_arb_1(
679                         false,
680                         numOfAASamples,
681                         needAlpha,
682                         needStencil,
683                         sRGB,
684                         &swapMethodOut);
685
686                 m_stereoVisual = false;  // set context property to actual value
687         }
688
689         if (swapMethodOut != WGL_SWAP_COPY_ARB) {
690                 fprintf(stderr,
691                         "Warning! Unable to find a pixel format that supports WGL_SWAP_COPY_ARB. "
692                         "Substituting one that uses %s.\n",
693                         swapMethodOut == WGL_SWAP_UNDEFINED_ARB ? "WGL_SWAP_UNDEFINED_ARB" : "WGL_SWAP_EXCHANGE_ARB");
694         }
695
696         return iPixelFormat;
697 }
698
699
700 int GHOST_ContextWGL::choose_pixel_format(
701         bool stereoVisual,
702         int  numOfAASamples,
703         bool needAlpha,
704         bool needStencil,
705         bool sRGB)
706 {
707         PIXELFORMATDESCRIPTOR preferredPFD = {
708                 sizeof(PIXELFORMATDESCRIPTOR),   /* size */
709                 1,                               /* version */
710                 PFD_SUPPORT_OPENGL |
711                 PFD_DRAW_TO_WINDOW |
712                 PFD_SWAP_COPY      |             /* support swap copy */
713                 PFD_DOUBLEBUFFER   |             /* support double-buffering */
714                 (stereoVisual ? PFD_STEREO : 0) |/* support stereo */
715                 (
716 #ifdef WIN32_COMPOSITING
717                 needAlpha ? PFD_SUPPORT_COMPOSITION :    /* support composition for transparent background */
718 #endif
719                 0
720                 ),
721                 PFD_TYPE_RGBA,                   /* color type */
722                 (needAlpha ? 32 : 24),           /* preferred color depth */
723                 0, 0, 0, 0, 0, 0,                /* color bits (ignored) */
724                 needAlpha ? 8 : 0,               /* alpha buffer */
725                 0,                               /* alpha shift (ignored) */
726                 0,                               /* no accumulation buffer */
727                 0, 0, 0, 0,                      /* accum bits (ignored) */
728                 24,                              /* depth buffer */
729                 needStencil ? 8 : 0,             /* stencil buffer */
730                 0,                               /* no auxiliary buffers */
731                 PFD_MAIN_PLANE,                  /* main layer */
732                 0,                               /* reserved */
733                 0, 0, 0                          /* layer, visible, and damage masks (ignored) */
734         };
735
736         initContextWGLEW(preferredPFD);
737
738         if (numOfAASamples > 0 && !WGLEW_ARB_multisample) {
739                 fprintf(stderr, "Warning! Unable to request a multisample framebuffer.\n");
740                 numOfAASamples = 0;
741         }
742
743         if (sRGB && !(WGLEW_ARB_framebuffer_sRGB || WGLEW_EXT_framebuffer_sRGB)) {
744                 fprintf(stderr, "Warning! Unable to request an sRGB framebuffer.\n");
745                 sRGB = false;
746         }
747
748         int iPixelFormat = 0;
749
750         if (WGLEW_ARB_pixel_format)
751                 iPixelFormat = choose_pixel_format_arb(stereoVisual, numOfAASamples, needAlpha, needStencil, sRGB);
752
753         if (iPixelFormat == 0)
754                 iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
755
756         return iPixelFormat;
757 }
758
759
760 #ifndef NDEBUG
761 static void reportContextString(const char *name, const char *dummy, const char *context)
762 {
763         fprintf(stderr, "%s: %s\n", name, context);
764
765         if (strcmp(dummy, context) != 0)
766                 fprintf(stderr, "Warning! Dummy %s: %s\n", name, dummy);
767 }
768 #endif
769
770
771 GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
772 {
773         const bool needAlpha = m_alphaBackground;
774
775 #ifdef GHOST_OPENGL_STENCIL
776         const bool needStencil = true;
777 #else
778         const bool needStencil = false;
779 #endif
780
781 #ifdef GHOST_OPENGL_SRGB
782         const bool sRGB = true;
783 #else
784         const bool sRGB = false;
785 #endif
786
787         HGLRC prevHGLRC;
788         HDC   prevHDC;
789
790         int iPixelFormat;
791         int lastPFD;
792
793         PIXELFORMATDESCRIPTOR chosenPFD;
794
795
796         SetLastError(NO_ERROR);
797
798         prevHGLRC = ::wglGetCurrentContext();
799         WIN32_CHK(GetLastError() == NO_ERROR);
800
801         prevHDC   = ::wglGetCurrentDC();
802         WIN32_CHK(GetLastError() == NO_ERROR);
803
804         iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
805
806         if (iPixelFormat == 0) {
807                 ::wglMakeCurrent(prevHDC, prevHGLRC);
808                 return GHOST_kFailure;
809         }
810
811         lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
812
813         if (!WIN32_CHK(lastPFD != 0)) {
814                 ::wglMakeCurrent(prevHDC, prevHGLRC);
815                 return GHOST_kFailure;
816         }
817
818         if (needAlpha && chosenPFD.cAlphaBits == 0)
819                 fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
820
821         if (needStencil && chosenPFD.cStencilBits == 0)
822                 fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");
823
824         if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
825                 ::wglMakeCurrent(prevHDC, prevHGLRC);
826                 return GHOST_kFailure;
827         }
828
829         activateWGLEW();
830
831         if (WGLEW_ARB_create_context) {
832                 int profileBitCore   = m_contextProfileMask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
833                 int profileBitCompat = m_contextProfileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
834
835 #ifdef WITH_GLEW_ES
836                 int profileBitES     = m_contextProfileMask & WGL_CONTEXT_ES_PROFILE_BIT_EXT;
837 #endif
838
839                 if (!WGLEW_ARB_create_context_profile && profileBitCore)
840                         fprintf(stderr, "Warning! OpenGL core profile not available.\n");
841
842                 if (!WGLEW_ARB_create_context_profile && profileBitCompat)
843                         fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
844
845 #ifdef WITH_GLEW_ES
846                 if (!WGLEW_EXT_create_context_es_profile && profileBitES && m_contextMajorVersion == 1)
847                         fprintf(stderr, "Warning! OpenGL ES profile not available.\n");
848
849                 if (!WGLEW_EXT_create_context_es2_profile && profileBitES && m_contextMajorVersion == 2)
850                         fprintf(stderr, "Warning! OpenGL ES2 profile not available.\n");
851 #endif
852
853                 int profileMask = 0;
854
855                 if (WGLEW_ARB_create_context_profile && profileBitCore)
856                         profileMask |= profileBitCore;
857
858                 if (WGLEW_ARB_create_context_profile && profileBitCompat)
859                         profileMask |= profileBitCompat;
860
861 #ifdef WITH_GLEW_ES
862                 if (WGLEW_EXT_create_context_es_profile && profileBitES)
863                         profileMask |= profileBitES;
864 #endif
865
866                 if (profileMask != m_contextProfileMask)
867                         fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
868
869                 std::vector<int> iAttributes;
870
871                 if (profileMask) {
872                         iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
873                         iAttributes.push_back(profileMask);
874                 }
875
876                 if (m_contextMajorVersion != 0) {
877                         iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
878                         iAttributes.push_back(m_contextMajorVersion);
879                 }
880
881                 if (m_contextMinorVersion != 0) {
882                         iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
883                         iAttributes.push_back(m_contextMinorVersion);
884                 }
885
886                 if (m_contextFlags != 0) {
887                         iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
888                         iAttributes.push_back(m_contextFlags);
889                 }
890
891                 if (m_contextResetNotificationStrategy != 0) {
892                         if (WGLEW_ARB_create_context_robustness) {
893                                 iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
894                                 iAttributes.push_back(m_contextResetNotificationStrategy);
895                         }
896                         else {
897                                 fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
898                         }
899                 }
900
901                 iAttributes.push_back(0);
902
903                 if (!s_singleContextMode || s_sharedHGLRC == NULL)
904                         m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
905                 else
906                         m_hGLRC = s_sharedHGLRC;
907         }
908         else {
909                 if (m_contextProfileMask  != 0)
910                         fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL profiles.");
911
912                 if (m_contextMajorVersion != 0 || m_contextMinorVersion != 0)
913                         fprintf(stderr, "Warning! Legacy WGL is unable to select between OpenGL versions.");
914
915                 if (m_contextFlags != 0)
916                         fprintf(stderr, "Warning! Legacy WGL is unable to set context flags.");
917
918                 if (!s_singleContextMode || s_sharedHGLRC == NULL)
919                         m_hGLRC = ::wglCreateContext(m_hDC);
920                 else
921                         m_hGLRC = s_sharedHGLRC;
922         }
923
924         if (!WIN32_CHK(m_hGLRC != NULL)) {
925                 ::wglMakeCurrent(prevHDC, prevHGLRC);
926                 return GHOST_kFailure;
927         }
928
929         if (s_sharedHGLRC == NULL)
930                 s_sharedHGLRC = m_hGLRC;
931
932         s_sharedCount++;
933
934         if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
935                 ::wglMakeCurrent(prevHDC, prevHGLRC);
936                 return GHOST_kFailure;
937         }
938
939         if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
940                 ::wglMakeCurrent(prevHDC, prevHGLRC);
941                 return GHOST_kFailure;
942         }
943
944         initContextGLEW();
945
946         initClearGL();
947         ::SwapBuffers(m_hDC);
948
949         const char *vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
950         const char *renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
951         const char *version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
952
953 #ifndef NDEBUG
954         reportContextString("Vendor",   m_dummyVendor,   vendor);
955         reportContextString("Renderer", m_dummyRenderer, renderer);
956         reportContextString("Version",  m_dummyVersion,  version);
957 #endif
958
959         if ((strcmp(vendor, "Microsoft Corporation") == 0 ||
960              strcmp(renderer, "GDI Generic") == 0) && version[0] == '1' && version[2] == '1')
961         {
962                 MessageBox(m_hWnd, "Your system does not use 3D hardware acceleration.\n"
963                                    "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
964                                    "This may be caused by:\n"
965                                    "* A missing or faulty graphics driver installation.\n"
966                                    "  Blender needs a graphics card driver to work correctly.\n"
967                                    "* Accessing Blender through a remote connection.\n"
968                                    "* Using Blender through a virtual machine.\n\n"
969                                    "The program will now close.",
970                            "Blender - Can't detect 3D hardware accelerated Driver!",
971                            MB_OK | MB_ICONERROR);
972                 exit(0);
973         }
974         else if (version[0] < '2' || (version[0] == '2' && version[2] < '1')) {
975                 MessageBox(m_hWnd, "Blender requires a graphics driver with OpenGL 2.1 support.\n\n"
976                                    "The program will now close.",
977                            "Blender - Unsupported Graphics Driver!",
978                            MB_OK | MB_ICONERROR);
979                 exit(0);
980         }
981
982         return GHOST_kSuccess;
983 }
984
985
986 GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
987 {
988         GHOST_TSuccess success = m_hGLRC != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess : GHOST_kFailure;
989
990         m_hWnd = NULL;
991         m_hDC  = NULL;
992
993         return success;
994 }