21 TypeHandle wglGraphicsStateGuardian::_type_handle;
23 const char *
const wglGraphicsStateGuardian::_twindow_class_name =
"wglGraphicsStateGuardian";
24 bool wglGraphicsStateGuardian::_twindow_class_registered =
false;
29 wglGraphicsStateGuardian::
32 GLGraphicsStateGuardian(engine, pipe),
33 _share_with(share_with)
35 _made_context =
false;
36 _context = (HGLRC)
nullptr;
42 _pfnum_supports_pbuffer =
false;
43 _pfnum_properties.clear();
45 _supports_pbuffer =
false;
46 _supports_pixel_format =
false;
47 _supports_wgl_multisample =
false;
48 _supports_wgl_render_texture =
false;
50 _wglCreateContextAttribsARB =
nullptr;
58 wglGraphicsStateGuardian::
59 ~wglGraphicsStateGuardian() {
61 if (_context != (HGLRC)
nullptr) {
62 wglDeleteContext(_context);
63 _context = (HGLRC)
nullptr;
82 if (_pfnum == _pre_pfnum) {
87 _pfnum_supports_pbuffer =
false;
88 _pfnum_properties = _pre_pfnum_properties;
99 PIXELFORMATDESCRIPTOR pfd;
100 ZeroMemory(&pfd,
sizeof(PIXELFORMATDESCRIPTOR));
101 pfd.nSize =
sizeof(PIXELFORMATDESCRIPTOR);
104 DescribePixelFormat(hdc, pfnum,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
109 if (((pfd.dwFlags & PFD_SUPPORT_OPENGL) == 0)||
110 ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) == 0)) {
116 if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
117 properties.set_indexed_color(1);
119 properties.set_alpha_bits(pfd.cAlphaBits);
121 properties.set_rgb_color(1);
123 pfd.cBlueBits, pfd.cAlphaBits);
126 if (pfd.dwFlags & PFD_DOUBLEBUFFER) {
127 properties.set_back_buffers(1);
129 if (pfd.dwFlags & PFD_STEREO) {
130 properties.set_stereo(1);
132 if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
133 properties.set_force_software(1);
135 properties.set_force_hardware(1);
138 if (pfd.cDepthBits != 0) {
139 properties.set_depth_bits(pfd.cDepthBits);
141 if (pfd.cStencilBits != 0) {
142 properties.set_stencil_bits(pfd.cStencilBits);
154 HDC window_dc,
int pfnum) {
156 static const int max_attrib_list = 32;
157 int iattrib_list[max_attrib_list];
158 int ivalue_list[max_attrib_list];
161 int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
162 color_bits_i, red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i,
163 accum_bits_i, depth_bits_i, stencil_bits_i, multisamples_i,
166 iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
167 iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
168 iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
169 iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
170 iattrib_list[color_bits_i = ni++] = WGL_COLOR_BITS_ARB;
171 iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB;
172 iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB;
173 iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB;
174 iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
175 iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB;
176 iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
177 iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
178 iattrib_list[srgb_capable_i = ni++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
180 if (_supports_wgl_multisample) {
181 iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
185 nassertr(ni <= max_attrib_list,
false);
187 if (!_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0,
188 ni, iattrib_list, ivalue_list)) {
195 if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) {
196 properties.set_force_software(
true);
198 properties.set_force_hardware(
true);
201 if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) {
202 properties.set_indexed_color(
true);
204 properties.set_alpha_bits(ivalue_list[alpha_bits_i]);
206 properties.set_rgb_color(
true);
208 ivalue_list[green_bits_i],
209 ivalue_list[blue_bits_i],
210 ivalue_list[alpha_bits_i]);
213 if (ivalue_list[double_buffer_i]) {
214 properties.set_back_buffers(1);
217 if (ivalue_list[stereo_i]) {
218 properties.set_stereo(
true);
221 if (ivalue_list[srgb_capable_i]) {
222 properties.set_srgb_color(
true);
225 if (ivalue_list[accum_bits_i] != 0) {
226 properties.set_accum_bits(ivalue_list[accum_bits_i]);
229 if (ivalue_list[depth_bits_i] != 0) {
230 properties.set_depth_bits(ivalue_list[depth_bits_i]);
233 if (ivalue_list[stencil_bits_i] != 0) {
234 properties.set_stencil_bits(ivalue_list[stencil_bits_i]);
237 if (_supports_wgl_multisample) {
238 if (ivalue_list[multisamples_i] != 0) {
239 properties.set_multisamples(ivalue_list[multisamples_i]);
258 wgldisplay_cat.info()
259 <<
"overriding pixfmt choice with gl-force-pixfmt("
260 << gl_force_pixfmt <<
")\n";
261 _pfnum = gl_force_pixfmt;
262 _pfnum_properties = properties;
263 _pfnum_supports_pbuffer =
true;
268 int best_quality = 0;
271 HDC hdc = GetDC(
nullptr);
273 int max_pfnum = DescribePixelFormat(hdc, 1, 0,
nullptr);
275 for (
int pfnum = 0; pfnum<max_pfnum; ++pfnum) {
279 if (quality > best_quality) {
281 best_quality = quality;
286 ReleaseDC(
nullptr, hdc);
289 _pfnum_supports_pbuffer =
false;
290 _pfnum_properties = best_prop;
292 _pre_pfnum_properties = _pfnum_properties;
294 if (best_quality == 0) {
295 wgldisplay_cat.error()
296 <<
"Could not find a usable pixel format.\n";
300 if (wgldisplay_cat.is_debug()) {
301 wgldisplay_cat.debug()
302 <<
"Preliminary pixfmt #" << _pfnum <<
" = "
303 << _pfnum_properties <<
"\n";
313 if (twindow_dc == 0) {
317 HGLRC twindow_ctx = wglCreateContext(twindow_dc);
318 if (twindow_ctx == 0) {
322 if (!wglGraphicsPipe::wgl_make_current(twindow_dc, twindow_ctx,
nullptr)) {
323 wgldisplay_cat.error()
324 <<
"Failed to make WGL context current.\n";
325 wglDeleteContext(twindow_ctx);
330 save_extensions((
const char *)GLP(GetString)(GL_EXTENSIONS));
331 get_extra_extensions();
332 _supports_pixel_format = has_extension(
"WGL_ARB_pixel_format");
333 _supports_wgl_multisample = has_extension(
"WGL_ARB_multisample");
335 if (has_extension(
"WGL_ARB_create_context")) {
336 _wglCreateContextAttribsARB =
337 (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(
"wglCreateContextAttribsARB");
339 _wglCreateContextAttribsARB =
nullptr;
344 if (!_supports_pixel_format) {
345 wglDeleteContext(twindow_ctx);
349 _wglGetPixelFormatAttribivARB =
350 (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribivARB");
351 _wglGetPixelFormatAttribfvARB =
352 (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribfvARB");
353 _wglChoosePixelFormatARB =
354 (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress(
"wglChoosePixelFormatARB");
356 if (_wglGetPixelFormatAttribivARB ==
nullptr ||
357 _wglGetPixelFormatAttribfvARB ==
nullptr ||
358 _wglChoosePixelFormatARB ==
nullptr) {
359 wgldisplay_cat.error()
360 <<
"Driver claims to support WGL_ARB_pixel_format extension, but does not define all functions.\n";
361 wglDeleteContext(twindow_ctx);
367 static const int max_attrib_list = 64;
368 int iattrib_list[max_attrib_list];
369 float fattrib_list[max_attrib_list];
373 iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
374 iattrib_list[ni++] =
true;
375 iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB;
376 iattrib_list[ni++] = WGL_TYPE_RGBA_ARB;
379 iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
380 iattrib_list[ni++] =
true;
381 if (_pfnum_properties.get_alpha_bits()) {
382 iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
383 iattrib_list[ni++] =
true;
385 iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB;
386 iattrib_list[ni++] =
true;
390 nassertv(ni < max_attrib_list && nf < max_attrib_list);
391 iattrib_list[ni] = 0;
392 fattrib_list[nf] = 0;
394 static const int max_pformats = 1024;
395 int pformat[max_pformats];
396 memset(pformat, 0,
sizeof(pformat));
399 if (!_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list,
400 max_pformats, pformat, (
unsigned int *)&nformats)) {
403 nformats = std::min(nformats, max_pformats);
405 if (wgldisplay_cat.is_debug()) {
406 wgldisplay_cat.debug()
407 <<
"Found " << nformats <<
" advanced formats: [";
408 for (
int i = 0; i < nformats; i++) {
409 wgldisplay_cat.debug(
false)
410 <<
" " << pformat[i];
412 wgldisplay_cat.debug(
false)
421 for (
int i = 0; i < nformats; i++) {
425 if (quality > best_quality) {
426 best_pfnum = pformat[i];
427 best_quality = quality;
433 if (!properties.get_srgb_color()) {
434 best_prop.set_srgb_color(
false);
438 _pfnum_supports_pbuffer = need_pbuffer;
439 _pfnum_properties = best_prop;
441 if (wgldisplay_cat.is_debug()) {
442 wgldisplay_cat.debug()
443 <<
"Selected advanced pixfmt #" << _pfnum <<
" = "
444 << _pfnum_properties <<
"\n";
448 wglDeleteContext(twindow_ctx);
457 GLGraphicsStateGuardian::reset();
459 _supports_swap_control = has_extension(
"WGL_EXT_swap_control");
461 if (_supports_swap_control) {
462 _wglSwapIntervalEXT =
463 (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress(
"wglSwapIntervalEXT");
464 if (_wglSwapIntervalEXT ==
nullptr) {
465 wgldisplay_cat.error()
466 <<
"Driver claims to support WGL_EXT_swap_control extension, but does not define all functions.\n";
467 _supports_swap_control =
false;
471 if (_supports_swap_control) {
474 _wglSwapIntervalEXT(sync_video ? 1 : 0);
477 _supports_pbuffer = has_extension(
"WGL_ARB_pbuffer");
479 if (_supports_pbuffer) {
480 _wglCreatePbufferARB =
481 (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress(
"wglCreatePbufferARB");
482 _wglGetPbufferDCARB =
483 (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress(
"wglGetPbufferDCARB");
484 _wglReleasePbufferDCARB =
485 (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress(
"wglReleasePbufferDCARB");
486 _wglDestroyPbufferARB =
487 (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress(
"wglDestroyPbufferARB");
488 _wglQueryPbufferARB =
489 (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress(
"wglQueryPbufferARB");
491 if (_wglCreatePbufferARB ==
nullptr ||
492 _wglGetPbufferDCARB ==
nullptr ||
493 _wglReleasePbufferDCARB ==
nullptr ||
494 _wglDestroyPbufferARB ==
nullptr ||
495 _wglQueryPbufferARB ==
nullptr) {
496 wgldisplay_cat.error()
497 <<
"Driver claims to support WGL_ARB_pbuffer extension, but does not define all functions.\n";
498 _supports_pbuffer =
false;
502 _supports_pixel_format = has_extension(
"WGL_ARB_pixel_format");
504 if (_supports_pixel_format) {
505 _wglGetPixelFormatAttribivARB =
506 (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribivARB");
507 _wglGetPixelFormatAttribfvARB =
508 (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribfvARB");
509 _wglChoosePixelFormatARB =
510 (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress(
"wglChoosePixelFormatARB");
512 if (_wglGetPixelFormatAttribivARB ==
nullptr ||
513 _wglGetPixelFormatAttribfvARB ==
nullptr ||
514 _wglChoosePixelFormatARB ==
nullptr) {
515 wgldisplay_cat.error()
516 <<
"Driver claims to support WGL_ARB_pixel_format extension, but does not define all functions.\n";
517 _supports_pixel_format =
false;
521 _supports_wgl_multisample = has_extension(
"WGL_ARB_multisample");
523 _supports_wgl_render_texture = has_extension(
"WGL_ARB_render_texture");
525 if (_supports_wgl_render_texture) {
526 _wglBindTexImageARB =
527 (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress(
"wglBindTexImageARB");
528 _wglReleaseTexImageARB =
529 (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress(
"wglReleaseTexImageARB");
530 _wglSetPbufferAttribARB =
531 (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress(
"wglSetPbufferAttribARB");
532 if (_wglBindTexImageARB ==
nullptr ||
533 _wglReleaseTexImageARB ==
nullptr ||
534 _wglSetPbufferAttribARB ==
nullptr) {
535 wgldisplay_cat.error()
536 <<
"Driver claims to support WGL_ARB_render_texture, but does not define all functions.\n";
537 _supports_wgl_render_texture =
false;
547 void wglGraphicsStateGuardian::
548 get_extra_extensions() {
554 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
555 (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress(
"wglGetExtensionsStringARB");
556 if (wglGetExtensionsStringARB !=
nullptr) {
557 HDC hdc = wglGetCurrentDC();
559 save_extensions((
const char *)wglGetExtensionsStringARB(hdc));
565 PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT =
566 (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress(
"wglGetExtensionsStringEXT");
567 if (wglGetExtensionsStringEXT !=
nullptr) {
568 save_extensions((
const char *)wglGetExtensionsStringEXT());
578 void *wglGraphicsStateGuardian::
579 do_get_extension_func(
const char *name) {
580 return (
void*) wglGetProcAddress(name);
587 void wglGraphicsStateGuardian::
588 make_context(HDC hdc) {
590 nassertv(!_made_context);
592 _made_context =
true;
595 wglGraphicsPipe::_current_valid =
false;
597 if (_wglCreateContextAttribsARB !=
nullptr) {
604 if (gl_version.get_num_words() > 0) {
605 attrib_list[n++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
606 attrib_list[n++] = gl_version[0];
607 if (gl_version.get_num_words() > 1) {
608 attrib_list[n++] = WGL_CONTEXT_MINOR_VERSION_ARB;
609 attrib_list[n++] = gl_version[1];
614 flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
616 if (gl_forward_compatible) {
617 flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
618 if (gl_version.get_num_words() == 0 || gl_version[0] < 2) {
619 wgldisplay_cat.error()
620 <<
"gl-forward-compatible requires gl-version >= 3 0\n";
624 attrib_list[n++] = WGL_CONTEXT_FLAGS_ARB;
625 attrib_list[n++] = flags;
627 #ifndef SUPPORT_FIXED_FUNCTION
628 attrib_list[n++] = WGL_CONTEXT_PROFILE_MASK_ARB;
629 attrib_list[n++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
633 _context = _wglCreateContextAttribsARB(hdc, 0, attrib_list);
635 _context = wglCreateContext(hdc);
638 if (_context ==
nullptr) {
639 wgldisplay_cat.error()
640 <<
"Could not create GL context.\n";
646 if (_share_with !=
nullptr) {
647 HGLRC share_context = _share_with->get_share_context();
648 if (share_context ==
nullptr) {
651 _share_with->redirect_share_pool(
this);
654 if (!wglShareLists(share_context, _context)) {
655 wgldisplay_cat.error()
656 <<
"Could not share texture contexts between wglGraphicsStateGuardians.\n";
662 _prepared_objects = _share_with->get_prepared_objects();
666 _share_with =
nullptr;
677 HGLRC wglGraphicsStateGuardian::
678 get_share_context()
const {
682 if (_share_with !=
nullptr) {
683 return _share_with->get_share_context();
696 void wglGraphicsStateGuardian::
698 nassertv(!_made_context);
699 if (_share_with !=
nullptr) {
700 _share_with->redirect_share_pool(share_with);
702 _share_with = share_with;
712 bool wglGraphicsStateGuardian::
716 DWORD window_style = 0;
718 register_twindow_class();
719 HINSTANCE hinstance = GetModuleHandle(
nullptr);
720 _twindow = CreateWindow(_twindow_class_name,
"twindow", window_style,
721 0, 0, 1, 1,
nullptr,
nullptr, hinstance, 0);
724 wgldisplay_cat.error()
725 <<
"CreateWindow() failed!" << std::endl;
729 ShowWindow(_twindow, SW_HIDE);
731 _twindow_dc = GetDC(_twindow);
733 PIXELFORMATDESCRIPTOR pixelformat;
734 if (!SetPixelFormat(_twindow_dc, _pfnum, &pixelformat)) {
735 wgldisplay_cat.error()
736 <<
"SetPixelFormat(" << _pfnum <<
") failed after window create\n";
748 void wglGraphicsStateGuardian::
751 ReleaseDC(_twindow, _twindow_dc);
755 DestroyWindow(_twindow);
764 void wglGraphicsStateGuardian::
765 register_twindow_class() {
766 if (_twindow_class_registered) {
772 HINSTANCE instance = GetModuleHandle(
nullptr);
775 ZeroMemory(&wc,
sizeof(WNDCLASS));
777 wc.lpfnWndProc = DefWindowProc;
778 wc.hInstance = instance;
779 wc.lpszClassName = _twindow_class_name;
781 if (!RegisterClass(&wc)) {
782 wgldisplay_cat.error()
783 <<
"could not register window class!" << std::endl;
786 _twindow_class_registered =
true;
789 #define GAMMA_1 (255.0 * 256.0)
791 static bool _gamma_table_initialized =
false;
792 static unsigned short _original_gamma_table [256 * 3];
794 void _create_gamma_table_wgl (PN_stdfloat gamma,
unsigned short *original_red_table,
unsigned short *original_green_table,
unsigned short *original_blue_table,
unsigned short *red_table,
unsigned short *green_table,
unsigned short *blue_table) {
796 double gamma_correction;
802 gamma_correction = 1.0 / (double) gamma;
804 for (i = 0; i < 256; i++) {
809 if (original_red_table) {
810 r = (double) original_red_table [i] / GAMMA_1;
811 g = (double) original_green_table [i] / GAMMA_1;
812 b = (double) original_blue_table [i] / GAMMA_1;
815 r = ((double) i / 255.0);
820 r = pow (r, gamma_correction);
821 g = pow (g, gamma_correction);
822 b = pow (b, gamma_correction);
852 if (_gamma_table_initialized ==
false) {
853 HDC hdc = GetDC(
nullptr);
856 if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
857 _gamma_table_initialized =
true;
861 ReleaseDC (
nullptr, hdc);
874 HDC hdc = GetDC(
nullptr);
878 unsigned short ramp [256 * 3];
880 if (restore && _gamma_table_initialized) {
881 _create_gamma_table_wgl (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
884 _create_gamma_table_wgl (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
887 if (SetDeviceGammaRamp (hdc, ramp)) {
891 static std::atomic_flag gamma_modified = ATOMIC_FLAG_INIT;
892 if (!gamma_modified.test_and_set()) {
897 ReleaseDC (
nullptr, hdc);