Blender V5.0
GHOST_ContextWGL.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "GHOST_ContextWGL.hh"
12
13#include <tchar.h>
14
15#include <cassert>
16#include <cstdio>
17#include <vector>
18
19HGLRC GHOST_ContextWGL::s_sharedHGLRC = nullptr;
20int GHOST_ContextWGL::s_sharedCount = 0;
21
22/* Some third-generation Intel video-cards are constantly bring problems */
24{
25 return strstr((const char *)glGetString(GL_VENDOR), "Intel") != nullptr;
26}
27
29 bool alphaBackground,
30 HWND hWnd,
31 HDC hDC,
32 int contextProfileMask,
33 int contextMajorVersion,
34 int contextMinorVersion,
35 int contextFlags,
36 int contextResetNotificationStrategy)
37 : GHOST_Context(context_params),
38 h_wnd_(hWnd),
39 h_DC_(hDC),
40 context_profile_mask_(contextProfileMask),
41 context_major_version_(contextMajorVersion),
42 context_minor_version_(contextMinorVersion),
43 context_flags_(contextFlags),
44 alpha_background_(alphaBackground),
45 context_reset_notification_strategy_(contextResetNotificationStrategy),
46 h_GLRC_(nullptr)
47#ifndef NDEBUG
48 ,
49 dummy_vendor_(nullptr),
50 dummy_renderer_(nullptr),
51 dummy_version_(nullptr)
52#endif
53{
54 assert(h_DC_ != nullptr);
55}
56
58{
59 if (h_GLRC_ != nullptr) {
60 if (h_GLRC_ == ::wglGetCurrentContext()) {
61 WIN32_CHK(::wglMakeCurrent(nullptr, nullptr));
62 }
63
64 if (h_GLRC_ != s_sharedHGLRC || s_sharedCount == 1) {
65 assert(s_sharedCount > 0);
66
67 s_sharedCount--;
68
69 if (s_sharedCount == 0) {
70 s_sharedHGLRC = nullptr;
71 }
72
73 WIN32_CHK(::wglDeleteContext(h_GLRC_));
74 }
75 }
76
77#ifndef NDEBUG
78 if (dummy_renderer_) {
79 free((void *)dummy_renderer_);
80 free((void *)dummy_vendor_);
81 free((void *)dummy_version_);
82 }
83#endif
84}
85
87{
88 return WIN32_CHK(::SwapBuffers(h_DC_)) ? GHOST_kSuccess : GHOST_kFailure;
89}
90
92{
93 if (epoxy_has_wgl_extension(h_DC_, "WGL_EXT_swap_control")) {
94 return WIN32_CHK(::wglSwapIntervalEXT(interval)) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
95 }
96 else {
97 return GHOST_kFailure;
98 }
99}
100
102{
103 if (epoxy_has_wgl_extension(h_DC_, "WGL_EXT_swap_control")) {
104 interval_out = ::wglGetSwapIntervalEXT();
105 return GHOST_kSuccess;
106 }
107 else {
108 return GHOST_kFailure;
109 }
110}
111
113{
114 if (WIN32_CHK(::wglMakeCurrent(h_DC_, h_GLRC_))) {
115 active_context_ = this;
116 return GHOST_kSuccess;
117 }
118 else {
119 return GHOST_kFailure;
120 }
121}
122
124{
125 /* Calling wglMakeCurrent(nullptr, nullptr) without an active context returns an error,
126 * so we always pass the device context handle. */
127 if (WIN32_CHK(::wglMakeCurrent(h_DC_, nullptr))) {
128 active_context_ = nullptr;
129 return GHOST_kSuccess;
130 }
131 else {
132 return GHOST_kFailure;
133 }
134}
135
136/* Ron Fosner's code for weighting pixel formats and forcing software.
137 * See http://www.opengl.org/resources/faq/technical/weight.cpp
138 */
139static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR &preferredPFD)
140{
141 int weight = 0;
142
143 /* assume desktop color depth is 32 bits per pixel */
144
145 /* cull unusable pixel formats */
146 /* if no formats can be found, can we determine why it was rejected? */
147 if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL) || !(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
148 !(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this. */
149 !(pfd.iPixelType == PFD_TYPE_RGBA) ||
150 (pfd.cColorBits > 32) || /* 64 bit formats disable AERO. */
151 (pfd.dwFlags & PFD_GENERIC_FORMAT)) /* No software renderers. */
152 {
153 return 0;
154 }
155
156 weight = 1; /* it's usable */
157
158 weight += pfd.cColorBits - 8;
159
160 if (preferredPFD.cAlphaBits > 0 && pfd.cAlphaBits > 0) {
161 weight++;
162 }
163
164 return weight;
165}
166
167/*
168 * A modification of Ron Fosner's replacement for ChoosePixelFormat
169 * returns 0 on error, else returns the pixel format number to be used
170 */
171static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
172{
173 int iPixelFormat = 0;
174 int weight = 0;
175
176 int iStereoPixelFormat = 0;
177 int stereoWeight = 0;
178
179 /* choose a pixel format using the useless Windows function in case we come up empty handed */
180 int iLastResortPixelFormat = ::ChoosePixelFormat(hDC, &preferredPFD);
181
182 WIN32_CHK(iLastResortPixelFormat != 0);
183
184 int lastPFD = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), nullptr);
185
186 WIN32_CHK(lastPFD != 0);
187
188 for (int i = 1; i <= lastPFD; i++) {
189 PIXELFORMATDESCRIPTOR pfd;
190 int check = ::DescribePixelFormat(hDC, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
191
192 WIN32_CHK(check == lastPFD);
193
194 int w = weight_pixel_format(pfd, preferredPFD);
195
196 if (w > weight) {
197 weight = w;
198 iPixelFormat = i;
199 }
200
201 if (w > stereoWeight && (preferredPFD.dwFlags & pfd.dwFlags & PFD_STEREO)) {
202 stereoWeight = w;
203 iStereoPixelFormat = i;
204 }
205 }
206
207 /* choose any available stereo format over a non-stereo format */
208 if (iStereoPixelFormat != 0) {
209 iPixelFormat = iStereoPixelFormat;
210 }
211
212 if (iPixelFormat == 0) {
213 fprintf(stderr, "Warning! Using result of ChoosePixelFormat.\n");
214 iPixelFormat = iLastResortPixelFormat;
215 }
216
217 return iPixelFormat;
218}
219
225static HWND clone_window(HWND hWnd, LPVOID lpParam)
226{
227 int count;
228
229 SetLastError(NO_ERROR);
230
231 DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
232 WIN32_CHK(GetLastError() == NO_ERROR);
233
234 WCHAR lpClassName[100] = L"";
235 count = GetClassNameW(hWnd, lpClassName, sizeof(lpClassName));
236 WIN32_CHK(count != 0);
237
238 WCHAR lpWindowName[100] = L"";
239 count = GetWindowTextW(hWnd, lpWindowName, sizeof(lpWindowName));
240 WIN32_CHK(count != 0);
241
242 DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
243 WIN32_CHK(GetLastError() == NO_ERROR);
244
245 RECT rect;
246 GetWindowRect(hWnd, &rect);
247 WIN32_CHK(GetLastError() == NO_ERROR);
248
249 HWND hWndParent = (HWND)GetWindowLongPtr(hWnd, GWLP_HWNDPARENT);
250 WIN32_CHK(GetLastError() == NO_ERROR);
251
252 HMENU hMenu = GetMenu(hWnd);
253 WIN32_CHK(GetLastError() == NO_ERROR);
254
255 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
256 WIN32_CHK(GetLastError() == NO_ERROR);
257
258 HWND hwndCloned = CreateWindowExW(dwExStyle,
259 lpClassName,
260 lpWindowName,
261 dwStyle,
262 rect.left,
263 rect.top,
264 rect.right - rect.left,
265 rect.bottom - rect.top,
266 hWndParent,
267 hMenu,
268 hInstance,
269 lpParam);
270
271 WIN32_CHK(hwndCloned != nullptr);
272
273 return hwndCloned;
274}
275
276static void makeAttribList(std::vector<int> &out, bool stereoVisual, bool needAlpha)
277{
278 out.clear();
279 out.reserve(30);
280
281 out.push_back(WGL_SUPPORT_OPENGL_ARB);
282 out.push_back(GL_TRUE);
283
284 out.push_back(WGL_DRAW_TO_WINDOW_ARB);
285 out.push_back(GL_TRUE);
286
287 out.push_back(WGL_DOUBLE_BUFFER_ARB);
288 out.push_back(GL_TRUE);
289
290 out.push_back(WGL_ACCELERATION_ARB);
291 out.push_back(WGL_FULL_ACCELERATION_ARB);
292
293 if (stereoVisual) {
294 out.push_back(WGL_STEREO_ARB);
295 out.push_back(GL_TRUE);
296 }
297
298 out.push_back(WGL_PIXEL_TYPE_ARB);
299 out.push_back(WGL_TYPE_RGBA_ARB);
300
301 out.push_back(WGL_COLOR_BITS_ARB);
302 out.push_back(24);
303
304 if (needAlpha) {
305 out.push_back(WGL_ALPHA_BITS_ARB);
306 out.push_back(8);
307 }
308
309 out.push_back(0);
310}
311
312/* Temporary context used to create the actual context. We need ARB pixel format
313 * and context extensions, which are only available within a context. */
315 HWND dummyHWND = nullptr;
316
317 HDC dummyHDC = nullptr;
318 HGLRC dummyHGLRC = nullptr;
319
320 HDC prevHDC = nullptr;
321 HGLRC prevHGLRC = nullptr;
322
324
325 PIXELFORMATDESCRIPTOR preferredPFD;
326
331
332 DummyContextWGL(HDC hDC, HWND hWnd, bool stereoVisual, bool needAlpha)
333 {
334 preferredPFD = {
335 sizeof(PIXELFORMATDESCRIPTOR), /* size */
336 1, /* version */
337 (DWORD)(PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW |
338 PFD_DOUBLEBUFFER | /* support double-buffering */
339 (stereoVisual ? PFD_STEREO : 0)), /* support stereo */
340 PFD_TYPE_RGBA, /* color type */
341 (BYTE)(needAlpha ? 32 : 24), /* preferred color depth */
342 0,
343 0,
344 0,
345 0,
346 0,
347 0, /* color bits (ignored) */
348 (BYTE)(needAlpha ? 8 : 0), /* alpha buffer */
349 0, /* alpha shift (ignored) */
350 0, /* no accumulation buffer */
351 0,
352 0,
353 0,
354 0, /* Accumulation bits (ignored). */
355 0, /* depth buffer */
356 0, /* stencil buffer */
357 0, /* no auxiliary buffers */
358 PFD_MAIN_PLANE, /* main layer */
359 0, /* reserved */
360 0,
361 0,
362 0 /* layer, visible, and damage masks (ignored) */
363 };
364
365 SetLastError(NO_ERROR);
366
367 prevHDC = ::wglGetCurrentDC();
368 WIN32_CHK(GetLastError() == NO_ERROR);
369
370 prevHGLRC = ::wglGetCurrentContext();
371 WIN32_CHK(GetLastError() == NO_ERROR);
372
374
375 if (dummyPixelFormat == 0) {
376 return;
377 }
378
379 PIXELFORMATDESCRIPTOR chosenPFD;
380 if (!WIN32_CHK(::DescribePixelFormat(
381 hDC, dummyPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
382 {
383 return;
384 }
385
386 if (hWnd) {
387 dummyHWND = clone_window(hWnd, nullptr);
388
389 if (dummyHWND == nullptr) {
390 return;
391 }
392
393 dummyHDC = GetDC(dummyHWND);
394 }
395
396 if (!WIN32_CHK(dummyHDC != nullptr)) {
397 return;
398 }
399
400 if (!WIN32_CHK(::SetPixelFormat(dummyHDC, dummyPixelFormat, &chosenPFD))) {
401 return;
402 }
403
404 dummyHGLRC = ::wglCreateContext(dummyHDC);
405
406 if (!WIN32_CHK(dummyHGLRC != nullptr)) {
407 return;
408 }
409
410 if (!WIN32_CHK(::wglMakeCurrent(dummyHDC, dummyHGLRC))) {
411 return;
412 }
413
414 has_WGL_ARB_pixel_format = epoxy_has_wgl_extension(hDC, "WGL_ARB_pixel_format");
415 has_WGL_ARB_create_context = epoxy_has_wgl_extension(hDC, "WGL_ARB_create_context");
416 has_WGL_ARB_create_context_profile = epoxy_has_wgl_extension(hDC,
417 "WGL_ARB_create_context_profile");
418 has_WGL_ARB_create_context_robustness = epoxy_has_wgl_extension(
419 hDC, "WGL_ARB_create_context_robustness");
420 }
421
423 {
424 WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
425
426 if (dummyHGLRC != nullptr) {
427 WIN32_CHK(::wglDeleteContext(dummyHGLRC));
428 }
429
430 if (dummyHWND != nullptr) {
431 if (dummyHDC != nullptr) {
432 WIN32_CHK(::ReleaseDC(dummyHWND, dummyHDC));
433 }
434
435 WIN32_CHK(::DestroyWindow(dummyHWND));
436 }
437 }
438};
439
440int GHOST_ContextWGL::_choose_pixel_format_arb_1(bool stereoVisual, bool needAlpha)
441{
442 std::vector<int> iAttributes;
443
444#define _MAX_PIXEL_FORMATS 32
445
446 int iPixelFormat = 0;
447 int iPixelFormats[_MAX_PIXEL_FORMATS];
448
449 makeAttribList(iAttributes, stereoVisual, needAlpha);
450
451 uint nNumFormats;
452 WIN32_CHK(wglChoosePixelFormatARB(
453 h_DC_, &(iAttributes[0]), nullptr, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
454
455 if (nNumFormats > 0) {
456 iPixelFormat = iPixelFormats[0];
457 }
458
459 // check pixel format
460 if (iPixelFormat != 0) {
461 if (needAlpha) {
462 int alphaBits, iQuery = WGL_ALPHA_BITS_ARB;
463 wglGetPixelFormatAttribivARB(h_DC_, iPixelFormat, 0, 1, &iQuery, &alphaBits);
464 if (alphaBits == 0) {
465 fprintf(stderr, "Warning! Unable to find a frame buffer with alpha channel.\n");
466 }
467 }
468 }
469 return iPixelFormat;
470}
471
472int GHOST_ContextWGL::choose_pixel_format_arb(bool stereoVisual, bool needAlpha)
473{
474 int iPixelFormat;
475
476 iPixelFormat = _choose_pixel_format_arb_1(stereoVisual, needAlpha);
477
478 if (iPixelFormat == 0 && stereoVisual) {
479 fprintf(stderr, "Warning! Unable to find a stereo pixel format.\n");
480
481 iPixelFormat = _choose_pixel_format_arb_1(false, needAlpha);
482
483 context_params_.is_stereo_visual = false; /* Set context property to actual value. */
484 }
485
486 return iPixelFormat;
487}
488
489#ifndef NDEBUG
490static void reportContextString(const char *name, const char *dummy, const char *context)
491{
492 fprintf(stderr, "%s: %s\n", name, context);
493
494 if (dummy && strcmp(dummy, context) != 0) {
495 fprintf(stderr, "Warning! Dummy %s: %s\n", name, dummy);
496 }
497}
498#endif
499
501{
502 SetLastError(NO_ERROR);
503
504 HGLRC prevHGLRC = ::wglGetCurrentContext();
505 WIN32_CHK(GetLastError() == NO_ERROR);
506
507 HDC prevHDC = ::wglGetCurrentDC();
508 WIN32_CHK(GetLastError() == NO_ERROR);
509
510 {
511 const bool needAlpha = alpha_background_;
512 DummyContextWGL dummy(h_DC_, h_wnd_, context_params_.is_stereo_visual, needAlpha);
513
514 if (!dummy.has_WGL_ARB_create_context || ::GetPixelFormat(h_DC_) == 0) {
515 int iPixelFormat = 0;
516
517 if (dummy.has_WGL_ARB_pixel_format) {
518 iPixelFormat = choose_pixel_format_arb(context_params_.is_stereo_visual, needAlpha);
519 }
520
521 if (iPixelFormat == 0) {
522 iPixelFormat = choose_pixel_format_legacy(h_DC_, dummy.preferredPFD);
523 }
524
525 if (iPixelFormat == 0) {
526 goto error;
527 }
528
529 PIXELFORMATDESCRIPTOR chosenPFD;
530 int lastPFD = ::DescribePixelFormat(
531 h_DC_, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
532
533 if (!WIN32_CHK(lastPFD != 0)) {
534 goto error;
535 }
536
537 if (needAlpha && chosenPFD.cAlphaBits == 0) {
538 fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
539 }
540
541 if (!WIN32_CHK(::SetPixelFormat(h_DC_, iPixelFormat, &chosenPFD))) {
542 goto error;
543 }
544 }
545
546 if (dummy.has_WGL_ARB_create_context) {
547 int profileBitCore = context_profile_mask_ & WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
548 int profileBitCompat = context_profile_mask_ & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
549
550 if (!dummy.has_WGL_ARB_create_context_profile && profileBitCore) {
551 fprintf(stderr, "Warning! OpenGL core profile not available.\n");
552 }
553
554 if (!dummy.has_WGL_ARB_create_context_profile && profileBitCompat) {
555 fprintf(stderr, "Warning! OpenGL compatibility profile not available.\n");
556 }
557
558 int profileMask = 0;
559
560 if (dummy.has_WGL_ARB_create_context_profile && profileBitCore) {
561 profileMask |= profileBitCore;
562 }
563
564 if (dummy.has_WGL_ARB_create_context_profile && profileBitCompat) {
565 profileMask |= profileBitCompat;
566 }
567
568 if (profileMask != context_profile_mask_) {
569 fprintf(stderr, "Warning! Ignoring untested OpenGL context profile mask bits.");
570 }
571
572 std::vector<int> iAttributes;
573
574 if (profileMask) {
575 iAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
576 iAttributes.push_back(profileMask);
577 }
578
579 if (context_major_version_ != 0) {
580 iAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
581 iAttributes.push_back(context_major_version_);
582 }
583
584 if (context_minor_version_ != 0) {
585 iAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
586 iAttributes.push_back(context_minor_version_);
587 }
588
589 if (context_flags_ != 0) {
590 iAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
591 iAttributes.push_back(context_flags_);
592 }
593
594 if (context_reset_notification_strategy_ != 0) {
596 iAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
597 iAttributes.push_back(context_reset_notification_strategy_);
598 }
599 else {
600 fprintf(stderr, "Warning! Cannot set the reset notification strategy.");
601 }
602 }
603
604 iAttributes.push_back(0);
605
606 h_GLRC_ = ::wglCreateContextAttribsARB(h_DC_, s_sharedHGLRC, &(iAttributes[0]));
607 }
608 }
609
610 /* Silence warnings interpreted as errors by users when trying to get
611 * a context with version higher than 3.3 Core. */
612 {
613 const bool silent = context_major_version_ > 3;
614 if (!WIN32_CHK_SILENT(h_GLRC_ != nullptr, silent)) {
615 goto error;
616 }
617 }
618
619 s_sharedCount++;
620
621 if (s_sharedHGLRC == nullptr) {
622 s_sharedHGLRC = h_GLRC_;
623 }
624
625 if (!WIN32_CHK(::wglMakeCurrent(h_DC_, h_GLRC_))) {
626 goto error;
627 }
628
629 {
630 const GHOST_TVSyncModes vsync = getVSync();
631 if (vsync != GHOST_kVSyncModeUnset) {
632 setSwapInterval(int(vsync));
633 }
634 }
635
636 if (is_crappy_intel_card()) {
637 /* Some Intel cards with context 4.1 or 4.2
638 * don't have the point sprite enabled by default.
639 *
640 * However GL_POINT_SPRITE was removed in 3.2 and is now permanently ON.
641 * Then use brute force. */
642 glEnable(GL_POINT_SPRITE);
643 }
644
645 initClearGL();
646 ::SwapBuffers(h_DC_);
647
648#ifndef NDEBUG
649 {
650 const char *vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
651 const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
652 const char *version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
653
654 reportContextString("Vendor", dummy_vendor_, vendor);
655 reportContextString("Renderer", dummy_renderer_, renderer);
656 reportContextString("Version", dummy_version_, version);
657
658 fprintf(stderr, "Context Version: %d.%d\n", context_major_version_, context_minor_version_);
659 }
660#endif
661
662 active_context_ = this;
663 return GHOST_kSuccess;
664error:
665 ::wglMakeCurrent(prevHDC, prevHGLRC);
666 return GHOST_kFailure;
667}
668
670{
671 GHOST_TSuccess success = h_GLRC_ != s_sharedHGLRC || s_sharedCount == 1 ? GHOST_kSuccess :
673
674 h_wnd_ = nullptr;
675 h_DC_ = nullptr;
676
677 return success;
678}
void BLI_kdtree_nd_ free(KDTree *tree)
unsigned int uint
static void makeAttribList(std::vector< int > &out, bool stereoVisual, bool needAlpha)
static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredPFD)
#define _MAX_PIXEL_FORMATS
static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR &preferredPFD)
static void reportContextString(const char *name, const char *dummy, const char *context)
static bool is_crappy_intel_card()
static HWND clone_window(HWND hWnd, LPVOID lpParam)
GHOST_TSuccess
Definition GHOST_Types.h:57
@ GHOST_kFailure
Definition GHOST_Types.h:57
@ GHOST_kSuccess
Definition GHOST_Types.h:57
GHOST_TVSyncModes
@ GHOST_kVSyncModeUnset
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
GHOST_ContextWGL(const GHOST_ContextParams &context_params, bool alphaBackground, HWND hWnd, HDC hDC, int contextProfileMask, int contextMajorVersion, int contextMinorVersion, int contextFlags, int contextResetNotificationStrategy)
GHOST_TSuccess releaseNativeHandles() override
GHOST_TSuccess releaseDrawingContext() override
GHOST_TSuccess initializeDrawingContext() override
GHOST_TSuccess setSwapInterval(int interval) override
~GHOST_ContextWGL() override
GHOST_TSuccess activateDrawingContext() override
GHOST_TSuccess getSwapInterval(int &interval_out) override
GHOST_TSuccess swapBufferRelease() override
GHOST_Context(const GHOST_ContextParams &context_params)
static GHOST_Context * active_context_
virtual GHOST_TVSyncModes getVSync()
GHOST_ContextParams context_params_
#define assert(assertion)
#define out
int count
#define L
static void error(const char *str)
const char * name
bool has_WGL_ARB_create_context_robustness
PIXELFORMATDESCRIPTOR preferredPFD
DummyContextWGL(HDC hDC, HWND hWnd, bool stereoVisual, bool needAlpha)
bool has_WGL_ARB_create_context_profile
i
Definition text_draw.cc:230