15 #include "wglGraphicsStateGuardian.h"
16 #include "wglGraphicsBuffer.h"
17 #include "string_utils.h"
19 TypeHandle wglGraphicsStateGuardian::_type_handle;
21 const char *
const wglGraphicsStateGuardian::_twindow_class_name =
"wglGraphicsStateGuardian";
22 bool wglGraphicsStateGuardian::_twindow_class_registered =
false;
29 wglGraphicsStateGuardian::
32 GLGraphicsStateGuardian(engine, pipe),
33 _share_with(share_with)
35 _made_context =
false;
36 _context = (HGLRC)NULL;
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;
59 wglGraphicsStateGuardian::
60 ~wglGraphicsStateGuardian() {
62 if (_context != (HGLRC)NULL) {
63 wglDeleteContext(_context);
64 _context = (HGLRC)NULL;
88 if (_pfnum == _pre_pfnum) {
93 _pfnum_supports_pbuffer =
false;
94 _pfnum_properties = _pre_pfnum_properties;
107 PIXELFORMATDESCRIPTOR pfd;
108 ZeroMemory(&pfd,
sizeof(PIXELFORMATDESCRIPTOR));
109 pfd.nSize =
sizeof(PIXELFORMATDESCRIPTOR);
112 DescribePixelFormat(hdc, pfnum,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
117 if (((pfd.dwFlags & PFD_SUPPORT_OPENGL) == 0)||
118 ((pfd.dwFlags & PFD_DRAW_TO_WINDOW) == 0)) {
124 if (pfd.iPixelType == PFD_TYPE_COLORINDEX) {
125 properties.set_indexed_color(1);
127 properties.set_alpha_bits(pfd.cAlphaBits);
129 properties.set_rgb_color(1);
131 pfd.cBlueBits, pfd.cAlphaBits);
135 if (pfd.dwFlags & PFD_DOUBLEBUFFER) {
136 properties.set_back_buffers(1);
138 if (pfd.dwFlags & PFD_STEREO) {
139 properties.set_stereo(1);
141 if (pfd.dwFlags & PFD_GENERIC_FORMAT) {
142 properties.set_force_software(1);
144 properties.set_force_hardware(1);
147 if (pfd.cDepthBits != 0) {
148 properties.set_depth_bits(pfd.cDepthBits);
150 if (pfd.cStencilBits != 0) {
151 properties.set_stencil_bits(pfd.cStencilBits);
166 HDC window_dc,
int pfnum) {
168 static const int max_attrib_list = 32;
169 int iattrib_list[max_attrib_list];
170 int ivalue_list[max_attrib_list];
173 int acceleration_i, pixel_type_i, double_buffer_i, stereo_i,
174 color_bits_i, red_bits_i, green_bits_i, blue_bits_i, alpha_bits_i,
175 accum_bits_i, depth_bits_i, stencil_bits_i, multisamples_i,
178 iattrib_list[acceleration_i = ni++] = WGL_ACCELERATION_ARB;
179 iattrib_list[pixel_type_i = ni++] = WGL_PIXEL_TYPE_ARB;
180 iattrib_list[double_buffer_i = ni++] = WGL_DOUBLE_BUFFER_ARB;
181 iattrib_list[stereo_i = ni++] = WGL_STEREO_ARB;
182 iattrib_list[color_bits_i = ni++] = WGL_COLOR_BITS_ARB;
183 iattrib_list[red_bits_i = ni++] = WGL_RED_BITS_ARB;
184 iattrib_list[green_bits_i = ni++] = WGL_GREEN_BITS_ARB;
185 iattrib_list[blue_bits_i = ni++] = WGL_BLUE_BITS_ARB;
186 iattrib_list[alpha_bits_i = ni++] = WGL_ALPHA_BITS_ARB;
187 iattrib_list[accum_bits_i = ni++] = WGL_ACCUM_BITS_ARB;
188 iattrib_list[depth_bits_i = ni++] = WGL_DEPTH_BITS_ARB;
189 iattrib_list[stencil_bits_i = ni++] = WGL_STENCIL_BITS_ARB;
190 iattrib_list[srgb_capable_i = ni++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
192 if (_supports_wgl_multisample) {
193 iattrib_list[multisamples_i = ni++] = WGL_SAMPLES_ARB;
197 nassertr(ni <= max_attrib_list,
false);
199 if (!_wglGetPixelFormatAttribivARB(window_dc, pfnum, 0,
200 ni, iattrib_list, ivalue_list)) {
207 int frame_buffer_mode = 0;
208 if (ivalue_list[acceleration_i] == WGL_NO_ACCELERATION_ARB) {
209 properties.set_force_software(
true);
211 properties.set_force_hardware(
true);
214 if (ivalue_list[pixel_type_i] == WGL_TYPE_COLORINDEX_ARB) {
215 properties.set_indexed_color(
true);
217 properties.set_alpha_bits(ivalue_list[alpha_bits_i]);
219 properties.set_rgb_color(
true);
221 ivalue_list[green_bits_i],
222 ivalue_list[blue_bits_i],
223 ivalue_list[alpha_bits_i]);
226 if (ivalue_list[double_buffer_i]) {
227 properties.set_back_buffers(1);
230 if (ivalue_list[stereo_i]) {
231 properties.set_stereo(
true);
234 if (ivalue_list[srgb_capable_i]) {
235 properties.set_srgb_color(
true);
238 if (ivalue_list[accum_bits_i] != 0) {
239 properties.set_accum_bits(ivalue_list[accum_bits_i]);
242 if (ivalue_list[depth_bits_i] != 0) {
243 properties.set_depth_bits(ivalue_list[depth_bits_i]);
246 if (ivalue_list[stencil_bits_i] != 0) {
247 properties.set_stencil_bits(ivalue_list[stencil_bits_i]);
250 if (_supports_wgl_multisample) {
251 if (ivalue_list[multisamples_i] != 0) {
252 properties.set_multisamples(ivalue_list[multisamples_i]);
275 wgldisplay_cat.info()
276 <<
"overriding pixfmt choice with gl-force-pixfmt("
277 << gl_force_pixfmt <<
")\n";
278 _pfnum = gl_force_pixfmt;
279 _pfnum_properties = properties;
280 _pfnum_supports_pbuffer =
true;
285 int best_quality = 0;
288 HDC hdc = GetDC(NULL);
290 int max_pfnum = DescribePixelFormat(hdc, 1, 0, NULL);
292 for (
int pfnum = 0; pfnum<max_pfnum; ++pfnum) {
296 if (quality > best_quality) {
298 best_quality = quality;
303 ReleaseDC(NULL, hdc);
306 _pfnum_supports_pbuffer =
false;
307 _pfnum_properties = best_prop;
309 _pre_pfnum_properties = _pfnum_properties;
311 if (best_quality == 0) {
312 wgldisplay_cat.error()
313 <<
"Could not find a usable pixel format.\n";
317 if (wgldisplay_cat.is_debug()) {
318 wgldisplay_cat.debug()
319 <<
"Preliminary pixfmt #" << _pfnum <<
" = "
320 << _pfnum_properties <<
"\n";
332 if (twindow_dc == 0) {
336 HGLRC twindow_ctx = wglCreateContext(twindow_dc);
337 if (twindow_ctx == 0) {
341 wglGraphicsPipe::wgl_make_current(twindow_dc, twindow_ctx, NULL);
344 save_extensions((
const char *)GLP(GetString)(GL_EXTENSIONS));
345 get_extra_extensions();
346 _supports_pixel_format = has_extension(
"WGL_ARB_pixel_format");
347 _supports_wgl_multisample = has_extension(
"WGL_ARB_multisample");
350 if (!_supports_pixel_format) {
351 wglDeleteContext(twindow_ctx);
355 _wglGetPixelFormatAttribivARB =
356 (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribivARB");
357 _wglGetPixelFormatAttribfvARB =
358 (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribfvARB");
359 _wglChoosePixelFormatARB =
360 (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress(
"wglChoosePixelFormatARB");
362 if (_wglGetPixelFormatAttribivARB == NULL ||
363 _wglGetPixelFormatAttribfvARB == NULL ||
364 _wglChoosePixelFormatARB == NULL) {
365 wgldisplay_cat.error()
366 <<
"Driver claims to support WGL_ARB_pixel_format extension, but does not define all functions.\n";
367 wglDeleteContext(twindow_ctx);
374 static const int max_attrib_list = 64;
375 int iattrib_list[max_attrib_list];
376 float fattrib_list[max_attrib_list];
380 iattrib_list[ni++] = WGL_SUPPORT_OPENGL_ARB;
381 iattrib_list[ni++] =
true;
382 iattrib_list[ni++] = WGL_PIXEL_TYPE_ARB;
383 iattrib_list[ni++] = WGL_TYPE_RGBA_ARB;
386 iattrib_list[ni++] = WGL_DRAW_TO_PBUFFER_ARB;
387 iattrib_list[ni++] =
true;
388 if (_pfnum_properties.get_alpha_bits()) {
389 iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGBA_ARB;
390 iattrib_list[ni++] =
true;
392 iattrib_list[ni++] = WGL_BIND_TO_TEXTURE_RGB_ARB;
393 iattrib_list[ni++] =
true;
397 nassertv(ni < max_attrib_list && nf < max_attrib_list);
398 iattrib_list[ni] = 0;
399 fattrib_list[nf] = 0;
401 static const int max_pformats = 1024;
402 int pformat[max_pformats];
403 memset(pformat, 0,
sizeof(pformat));
406 if (!_wglChoosePixelFormatARB(twindow_dc, iattrib_list, fattrib_list,
407 max_pformats, pformat, (
unsigned int *)&nformats)) {
410 nformats = min(nformats, max_pformats);
412 if (wgldisplay_cat.is_debug()) {
413 wgldisplay_cat.debug()
414 <<
"Found " << nformats <<
" advanced formats: [";
415 for (
int i = 0; i < nformats; i++) {
416 wgldisplay_cat.debug(
false)
417 <<
" " << pformat[i];
419 wgldisplay_cat.debug(
false)
428 for (
int i = 0; i < nformats; i++) {
432 if (quality > best_quality) {
433 best_pfnum = pformat[i];
434 best_quality = quality;
440 if (!properties.get_srgb_color()) {
441 best_prop.set_srgb_color(
false);
445 _pfnum_supports_pbuffer = need_pbuffer;
446 _pfnum_properties = best_prop;
448 if (wgldisplay_cat.is_debug()) {
449 wgldisplay_cat.debug()
450 <<
"Selected advanced pixfmt #" << _pfnum <<
" = "
451 << _pfnum_properties <<
"\n";
455 wglDeleteContext(twindow_ctx);
467 GLGraphicsStateGuardian::reset();
469 _supports_swap_control = has_extension(
"WGL_EXT_swap_control");
471 if (_supports_swap_control) {
472 _wglSwapIntervalEXT =
473 (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress(
"wglSwapIntervalEXT");
474 if (_wglSwapIntervalEXT == NULL) {
475 wgldisplay_cat.error()
476 <<
"Driver claims to support WGL_EXT_swap_control extension, but does not define all functions.\n";
477 _supports_swap_control =
false;
481 if (_supports_swap_control) {
484 _wglSwapIntervalEXT(sync_video ? 1 : 0);
487 _supports_pbuffer = has_extension(
"WGL_ARB_pbuffer");
489 if (_supports_pbuffer) {
490 _wglCreatePbufferARB =
491 (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress(
"wglCreatePbufferARB");
492 _wglGetPbufferDCARB =
493 (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress(
"wglGetPbufferDCARB");
494 _wglReleasePbufferDCARB =
495 (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress(
"wglReleasePbufferDCARB");
496 _wglDestroyPbufferARB =
497 (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress(
"wglDestroyPbufferARB");
498 _wglQueryPbufferARB =
499 (PFNWGLQUERYPBUFFERARBPROC)wglGetProcAddress(
"wglQueryPbufferARB");
501 if (_wglCreatePbufferARB == NULL ||
502 _wglGetPbufferDCARB == NULL ||
503 _wglReleasePbufferDCARB == NULL ||
504 _wglDestroyPbufferARB == NULL ||
505 _wglQueryPbufferARB == NULL) {
506 wgldisplay_cat.error()
507 <<
"Driver claims to support WGL_ARB_pbuffer extension, but does not define all functions.\n";
508 _supports_pbuffer =
false;
512 _supports_pixel_format = has_extension(
"WGL_ARB_pixel_format");
514 if (_supports_pixel_format) {
515 _wglGetPixelFormatAttribivARB =
516 (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribivARB");
517 _wglGetPixelFormatAttribfvARB =
518 (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)wglGetProcAddress(
"wglGetPixelFormatAttribfvARB");
519 _wglChoosePixelFormatARB =
520 (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress(
"wglChoosePixelFormatARB");
522 if (_wglGetPixelFormatAttribivARB == NULL ||
523 _wglGetPixelFormatAttribfvARB == NULL ||
524 _wglChoosePixelFormatARB == NULL) {
525 wgldisplay_cat.error()
526 <<
"Driver claims to support WGL_ARB_pixel_format extension, but does not define all functions.\n";
527 _supports_pixel_format =
false;
531 _supports_wgl_multisample = has_extension(
"WGL_ARB_multisample");
533 _supports_wgl_render_texture = has_extension(
"WGL_ARB_render_texture");
535 if (_supports_wgl_render_texture) {
536 _wglBindTexImageARB =
537 (PFNWGLBINDTEXIMAGEARBPROC)wglGetProcAddress(
"wglBindTexImageARB");
538 _wglReleaseTexImageARB =
539 (PFNWGLRELEASETEXIMAGEARBPROC)wglGetProcAddress(
"wglReleaseTexImageARB");
540 _wglSetPbufferAttribARB =
541 (PFNWGLSETPBUFFERATTRIBARBPROC)wglGetProcAddress(
"wglSetPbufferAttribARB");
542 if (_wglBindTexImageARB == NULL ||
543 _wglReleaseTexImageARB == NULL ||
544 _wglSetPbufferAttribARB == NULL) {
545 wgldisplay_cat.error()
546 <<
"Driver claims to support WGL_ARB_render_texture, but does not define all functions.\n";
547 _supports_wgl_render_texture =
false;
560 void wglGraphicsStateGuardian::
561 get_extra_extensions() {
567 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
568 (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress(
"wglGetExtensionsStringARB");
569 if (wglGetExtensionsStringARB != NULL) {
570 HDC hdc = wglGetCurrentDC();
572 save_extensions((
const char *)wglGetExtensionsStringARB(hdc));
579 PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT =
580 (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress(
"wglGetExtensionsStringEXT");
581 if (wglGetExtensionsStringEXT != NULL) {
582 save_extensions((
const char *)wglGetExtensionsStringEXT());
596 void *wglGraphicsStateGuardian::
597 do_get_extension_func(
const char *name) {
598 return (
void*) wglGetProcAddress(name);
608 void wglGraphicsStateGuardian::
609 make_context(HDC hdc) {
611 nassertv(!_made_context);
613 _made_context =
true;
616 wglGraphicsPipe::_current_valid =
false;
617 _context = wglCreateContext(hdc);
619 if (_context == NULL) {
620 wgldisplay_cat.error()
621 <<
"Could not create GL context.\n";
628 HGLRC share_context = _share_with->get_share_context();
629 if (share_context == NULL) {
632 _share_with->redirect_share_pool(
this);
635 if (!wglShareLists(share_context, _context)) {
636 wgldisplay_cat.error()
637 <<
"Could not share texture contexts between wglGraphicsStateGuardians.\n";
643 _prepared_objects = _share_with->get_prepared_objects();
662 HGLRC wglGraphicsStateGuardian::
663 get_share_context()
const {
668 return _share_with->get_share_context();
686 void wglGraphicsStateGuardian::
688 nassertv(!_made_context);
690 _share_with->redirect_share_pool(share_with);
692 _share_with = share_with;
706 bool wglGraphicsStateGuardian::
710 DWORD window_style = 0;
712 register_twindow_class();
713 HINSTANCE hinstance = GetModuleHandle(NULL);
714 _twindow = CreateWindow(_twindow_class_name,
"twindow", window_style,
715 0, 0, 1, 1, NULL, NULL, hinstance, 0);
718 wgldisplay_cat.error()
719 <<
"CreateWindow() failed!" << endl;
723 ShowWindow(_twindow, SW_HIDE);
725 _twindow_dc = GetDC(_twindow);
727 PIXELFORMATDESCRIPTOR pixelformat;
728 if (!SetPixelFormat(_twindow_dc, _pfnum, &pixelformat)) {
729 wgldisplay_cat.error()
730 <<
"SetPixelFormat(" << _pfnum <<
") failed after window create\n";
745 void wglGraphicsStateGuardian::
748 ReleaseDC(_twindow, _twindow_dc);
752 DestroyWindow(_twindow);
764 void wglGraphicsStateGuardian::
765 register_twindow_class() {
766 if (_twindow_class_registered) {
772 HINSTANCE instance = GetModuleHandle(NULL);
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!" << 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 _orignial_gamma_table [256 * 3];
794 void _create_gamma_table (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);
854 if (_gamma_table_initialized ==
false) {
855 HDC hdc = GetDC(NULL);
858 if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
859 _gamma_table_initialized =
true;
863 ReleaseDC (NULL, hdc);
879 HDC hdc = GetDC(NULL);
883 unsigned short ramp [256 * 3];
885 if (restore && _gamma_table_initialized) {
886 _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
889 _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
892 if (SetDeviceGammaRamp (hdc, ramp)) {
896 ReleaseDC (NULL, 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...
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.
bool has_value() const
Returns true if this variable has an explicit value, either from a prc file or locally set...
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...
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.
int get_quality(const FrameBufferProperties &reqs) const
Assumes that these properties are a description of a window.
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.
void get_properties(FrameBufferProperties &properties, HDC hdc, int pfnum)
Gets the FrameBufferProperties to match the indicated pixel format descriptor.
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.
void set_color_bits(int n)
Sets the number of requested color bits as a single number that represents the sum of the individual ...
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...