20 TypeHandle wglGraphicsStateGuardian::_type_handle;
22 const char *
const wglGraphicsStateGuardian::_twindow_class_name =
"wglGraphicsStateGuardian";
23 bool wglGraphicsStateGuardian::_twindow_class_registered =
false;
28 wglGraphicsStateGuardian::
31 GLGraphicsStateGuardian(engine, pipe),
32 _share_with(share_with)
34 _made_context =
false;
35 _context = (HGLRC)
nullptr;
41 _pfnum_supports_pbuffer =
false;
42 _pfnum_properties.clear();
44 _supports_pbuffer =
false;
45 _supports_pixel_format =
false;
46 _supports_wgl_multisample =
false;
47 _supports_wgl_render_texture =
false;
49 _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];
613 attrib_list[n++] = WGL_CONTEXT_FLAGS_ARB;
614 attrib_list[n++] = WGL_CONTEXT_DEBUG_BIT_ARB;
616 #ifndef SUPPORT_FIXED_FUNCTION 617 attrib_list[n++] = WGL_CONTEXT_PROFILE_MASK_ARB;
618 attrib_list[n++] = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
622 _context = _wglCreateContextAttribsARB(hdc, 0, attrib_list);
624 _context = wglCreateContext(hdc);
627 if (_context ==
nullptr) {
628 wgldisplay_cat.error()
629 <<
"Could not create GL context.\n";
635 if (_share_with !=
nullptr) {
636 HGLRC share_context = _share_with->get_share_context();
637 if (share_context ==
nullptr) {
640 _share_with->redirect_share_pool(
this);
643 if (!wglShareLists(share_context, _context)) {
644 wgldisplay_cat.error()
645 <<
"Could not share texture contexts between wglGraphicsStateGuardians.\n";
651 _prepared_objects = _share_with->get_prepared_objects();
655 _share_with =
nullptr;
666 HGLRC wglGraphicsStateGuardian::
667 get_share_context()
const {
671 if (_share_with !=
nullptr) {
672 return _share_with->get_share_context();
685 void wglGraphicsStateGuardian::
687 nassertv(!_made_context);
688 if (_share_with !=
nullptr) {
689 _share_with->redirect_share_pool(share_with);
691 _share_with = share_with;
701 bool wglGraphicsStateGuardian::
705 DWORD window_style = 0;
707 register_twindow_class();
708 HINSTANCE hinstance = GetModuleHandle(
nullptr);
709 _twindow = CreateWindow(_twindow_class_name,
"twindow", window_style,
710 0, 0, 1, 1,
nullptr,
nullptr, hinstance, 0);
713 wgldisplay_cat.error()
714 <<
"CreateWindow() failed!" << std::endl;
718 ShowWindow(_twindow, SW_HIDE);
720 _twindow_dc = GetDC(_twindow);
722 PIXELFORMATDESCRIPTOR pixelformat;
723 if (!SetPixelFormat(_twindow_dc, _pfnum, &pixelformat)) {
724 wgldisplay_cat.error()
725 <<
"SetPixelFormat(" << _pfnum <<
") failed after window create\n";
737 void wglGraphicsStateGuardian::
740 ReleaseDC(_twindow, _twindow_dc);
744 DestroyWindow(_twindow);
753 void wglGraphicsStateGuardian::
754 register_twindow_class() {
755 if (_twindow_class_registered) {
761 HINSTANCE instance = GetModuleHandle(
nullptr);
764 ZeroMemory(&wc,
sizeof(WNDCLASS));
766 wc.lpfnWndProc = DefWindowProc;
767 wc.hInstance = instance;
768 wc.lpszClassName = _twindow_class_name;
770 if (!RegisterClass(&wc)) {
771 wgldisplay_cat.error()
772 <<
"could not register window class!" << std::endl;
775 _twindow_class_registered =
true;
778 #define GAMMA_1 (255.0 * 256.0) 780 static bool _gamma_table_initialized =
false;
781 static unsigned short _original_gamma_table [256 * 3];
783 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) {
785 double gamma_correction;
791 gamma_correction = 1.0 / (double) gamma;
793 for (i = 0; i < 256; i++) {
798 if (original_red_table) {
799 r = (double) original_red_table [i] / GAMMA_1;
800 g = (double) original_green_table [i] / GAMMA_1;
801 b = (double) original_blue_table [i] / GAMMA_1;
804 r = ((double) i / 255.0);
809 r = pow (r, gamma_correction);
810 g = pow (g, gamma_correction);
811 b = pow (b, gamma_correction);
841 if (_gamma_table_initialized ==
false) {
842 HDC hdc = GetDC(
nullptr);
845 if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
846 _gamma_table_initialized =
true;
850 ReleaseDC (
nullptr, hdc);
863 HDC hdc = GetDC(
nullptr);
867 unsigned short ramp [256 * 3];
869 if (restore && _gamma_table_initialized) {
870 _create_gamma_table_wgl (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
873 _create_gamma_table_wgl (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
876 if (SetDeviceGammaRamp (hdc, ramp)) {
880 ReleaseDC (
nullptr, hdc);
void set_all_specified()
Marks all bits as having been specified.
HDC get_twindow_dc()
Returns the DC associated with the temporary, invisible window that was created with the gsg to query...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear()
Unsets all properties that have been specified so far, and resets the FrameBufferProperties structure...
bool set_gamma(PN_stdfloat gamma)
Non static version of setting gamma.
static bool get_gamma_table(void)
Static function for getting the original gamma.
void restore_gamma()
Restore original gamma.
static bool static_set_gamma(bool restore, PN_stdfloat gamma)
Static function for setting gamma which is needed for atexit.
bool get_properties_advanced(FrameBufferProperties &properties, HDC hdc, int pfnum)
Gets the FrameBufferProperties to match the indicated pixel format descriptor, using the WGL extensio...
bool fail_pfnum()
This is called by wglGraphicsWindow when it finds it cannot use the pfnum determined by the GSG.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
virtual void reset()
Resets all internal state as if the gsg were newly created.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void atexit_function(void)
This function is passed to the atexit function.
void choose_pixel_format(const FrameBufferProperties &properties, bool need_pbuffer)
Selects a pixel format for all the windows and buffers that use this gsg.
An object to create GraphicsOutputs that share a particular 3-D API.
set_color_bits
Sets the number of requested color bits as a single number that represents the sum of the individual ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void get_properties(FrameBufferProperties &properties, HDC hdc, int pfnum)
Gets the FrameBufferProperties to match the indicated pixel format descriptor.
bool has_value() const
Returns true if this variable has an explicit value, either from a prc file or locally set,...
void set_rgba_bits(int r, int g, int b, int a)
Convenience method for setting the red, green, blue and alpha bits in one go.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
int get_quality(const FrameBufferProperties &reqs) const
Assumes that these properties are a description of a window.