15 #include "glxGraphicsStateGuardian.h" 16 #include "config_glxdisplay.h" 17 #include "config_glgsg.h" 18 #include "lightReMutexHolder.h" 23 TypeHandle glxGraphicsStateGuardian::_type_handle;
30 glxGraphicsStateGuardian::
42 _context_has_pbuffer =
false;
43 _context_has_pixmap =
false;
46 _supports_swap_control =
false;
47 _supports_fbconfig =
false;
48 _supports_pbuffer =
false;
49 _uses_sgix_pbuffer =
false;
52 _prepared_objects = share_with->get_prepared_objects();
53 _share_context = share_with->_context;
56 _checked_get_proc_address =
false;
57 _glXGetProcAddress = NULL;
58 _temp_context = (GLXContext)NULL;
59 _temp_xwindow = (X11_Window)NULL;
60 _temp_colormap = (Colormap)NULL;
68 glxGraphicsStateGuardian::
69 ~glxGraphicsStateGuardian() {
70 destroy_temp_xwindow();
71 if (_visuals != (XVisualInfo *)NULL) {
74 if (_context != (GLXContext)NULL) {
75 glXDestroyContext(_display, _context);
76 _context = (GLXContext)NULL;
89 int use_gl, render_mode, double_buffer, stereo,
90 red_size, green_size, blue_size,
91 alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
92 depth_size, stencil_size;
94 glXGetConfig(_display, visual, GLX_USE_GL, &use_gl);
95 glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
96 glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
97 glXGetConfig(_display, visual, GLX_STEREO, &stereo);
98 glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
99 glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
100 glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
101 glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
102 glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
103 glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
104 glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
105 glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
106 glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
107 glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
119 properties.set_back_buffers(1);
122 properties.set_stereo(1);
125 properties.set_rgb_color(1);
127 properties.set_indexed_color(1);
130 properties.
set_rgba_bits(red_size, green_size, blue_size, alpha_size);
131 properties.set_stencil_bits(stencil_size);
132 properties.set_depth_bits(depth_size);
133 properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
136 properties.set_force_software(1);
137 properties.set_force_hardware(1);
148 bool &context_has_pbuffer,
bool &context_has_pixmap,
149 bool &slow, GLXFBConfig config) {
152 if (_supports_fbconfig) {
154 int render_type, double_buffer, stereo, red_size, green_size, blue_size,
155 alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
156 depth_size, stencil_size, samples, drawable_type, caveat, srgb_capable;
158 _glXGetFBConfigAttrib(_display, config, GLX_RENDER_TYPE, &render_type);
159 _glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer);
160 _glXGetFBConfigAttrib(_display, config, GLX_STEREO, &stereo);
161 _glXGetFBConfigAttrib(_display, config, GLX_RED_SIZE, &red_size);
162 _glXGetFBConfigAttrib(_display, config, GLX_GREEN_SIZE, &green_size);
163 _glXGetFBConfigAttrib(_display, config, GLX_BLUE_SIZE, &blue_size);
164 _glXGetFBConfigAttrib(_display, config, GLX_ALPHA_SIZE, &alpha_size);
165 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_RED_SIZE, &ared_size);
166 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_GREEN_SIZE, &agreen_size);
167 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_BLUE_SIZE, &ablue_size);
168 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
169 _glXGetFBConfigAttrib(_display, config, GLX_DEPTH_SIZE, &depth_size);
170 _glXGetFBConfigAttrib(_display, config, GLX_STENCIL_SIZE, &stencil_size);
171 _glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples);
172 _glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
173 _glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
174 _glXGetFBConfigAttrib(_display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
176 context_has_pbuffer =
false;
177 if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
178 context_has_pbuffer =
true;
181 context_has_pixmap =
false;
182 if ((drawable_type & GLX_PIXMAP_BIT)!=0) {
183 context_has_pixmap =
true;
187 if (caveat == GLX_SLOW_CONFIG) {
191 if ((drawable_type & GLX_WINDOW_BIT)==0) {
197 properties.set_back_buffers(1);
201 properties.set_stereo(
true);
205 properties.set_srgb_color(
true);
208 if ((render_type & GLX_RGBA_BIT)!=0) {
209 properties.set_rgb_color(
true);
211 if ((render_type & GLX_COLOR_INDEX_BIT)!=0) {
212 properties.set_indexed_color(
true);
215 properties.
set_rgba_bits(red_size, green_size, blue_size, alpha_size);
216 properties.set_stencil_bits(stencil_size);
217 properties.set_depth_bits(depth_size);
218 properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
219 properties.set_multisamples(samples);
222 properties.set_force_software(1);
223 properties.set_force_hardware(1);
236 X11_Display *display,
237 int screen,
bool need_pbuffer,
bool need_pixmap) {
244 if (_visuals != (XVisualInfo *)NULL) {
255 destroy_temp_xwindow();
256 choose_temp_visual(properties);
257 if (_temp_context == NULL) {
268 if (!_supports_fbconfig) {
271 glxdisplay_cat.debug()
272 <<
" No FBConfig supported; using XVisual only.\n" 275 _context = _temp_context;
276 _temp_context = (GLXContext)NULL;
281 _context_has_pixmap = !glXIsDirect(_display, _context);
284 _context_has_pbuffer =
false;
293 int best_quality = 0;
297 int render_type = GLX_RGBA_TYPE;
298 if (properties.get_indexed_color()) {
299 render_type = GLX_COLOR_INDEX_TYPE;
302 static const int max_attrib_list = 32;
303 int attrib_list[max_attrib_list];
305 attrib_list[n++] = GLX_STEREO;
306 attrib_list[n++] = GLX_DONT_CARE;
307 attrib_list[n++] = GLX_RENDER_TYPE;
308 attrib_list[n++] = GLX_DONT_CARE;
309 attrib_list[n++] = GLX_DRAWABLE_TYPE;
310 attrib_list[n++] = GLX_DONT_CARE;
311 attrib_list[n] = (int)None;
314 GLXFBConfig *configs =
315 _glXChooseFBConfig(_display, _screen, attrib_list, &num_configs);
318 bool context_has_pbuffer, context_has_pixmap, slow;
320 for (i = 0; i < num_configs; ++i) {
325 if ((quality > 0)&&(slow)) quality -= 10000000;
326 if (glxdisplay_cat.is_debug()) {
327 const char *pbuffertext = context_has_pbuffer ?
" (pbuffer)" :
"";
328 const char *pixmaptext = context_has_pixmap ?
" (pixmap)" :
"";
329 const char *slowtext = slow ?
" (slow)" :
"";
330 glxdisplay_cat.debug()
331 << i <<
": " << fbprops <<
" quality=" << quality << pbuffertext
332 << pixmaptext << slowtext <<
"\n";
334 if (need_pbuffer && !context_has_pbuffer) {
337 if (need_pixmap && !context_has_pixmap) {
341 if (quality > best_quality) {
342 best_quality = quality;
344 best_props = fbprops;
349 if (best_quality > 0) {
350 _fbconfig = configs[best_result];
352 if (_glXCreateContextAttribs != NULL) {
356 attrib_list[n++] = GLX_RENDER_TYPE;
357 attrib_list[n++] = render_type;
359 attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB;
360 attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB;
362 attrib_list[n] = None;
363 _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context,
364 GL_TRUE, attrib_list);
367 _glXCreateNewContext(_display, _fbconfig, render_type, _share_context,
374 if (_visuals != (XVisualInfo *)NULL) {
378 _visuals = _glXGetVisualFromFBConfig(_display, _fbconfig);
385 if (!properties.get_srgb_color()) {
386 _fbprops.set_srgb_color(
false);
389 if (glxdisplay_cat.is_debug()) {
390 glxdisplay_cat.debug()
391 <<
"Selected context " << best_result <<
": " << _fbprops <<
"\n";
392 glxdisplay_cat.debug()
393 <<
"context_has_pbuffer = " << _context_has_pbuffer
394 <<
", context_has_pixmap = " << _context_has_pixmap <<
"\n";
401 glxdisplay_cat.error()
402 <<
"Could not create FBConfig context!\n";
409 glxdisplay_cat.warning()
410 <<
"No suitable FBConfig contexts available; using XVisual only.\n" 413 _context = _temp_context;
414 _temp_context = (GLXContext)NULL;
419 _context_has_pixmap = !glXIsDirect(_display, _context);
422 _context_has_pbuffer =
false;
433 if (_glx_version_major < major_version) {
436 if (_glx_version_major > major_version) {
439 if (_glx_version_minor < minor_version) {
450 void glxGraphicsStateGuardian::
454 PosixGraphicsStateGuardian::gl_flush();
462 GLenum glxGraphicsStateGuardian::
463 gl_get_error()
const {
466 return PosixGraphicsStateGuardian::gl_get_error();
474 void glxGraphicsStateGuardian::
476 PosixGraphicsStateGuardian::query_gl_version();
478 show_glx_client_string(
"GLX_VENDOR", GLX_VENDOR);
479 show_glx_client_string(
"GLX_VERSION", GLX_VERSION);
480 show_glx_server_string(
"GLX_VENDOR", GLX_VENDOR);
481 show_glx_server_string(
"GLX_VERSION", GLX_VERSION);
483 glXQueryVersion(_display, &_glx_version_major, &_glx_version_minor);
488 if (glgsg_cat.is_debug()) {
490 <<
"GLX_VERSION = " << _glx_version_major <<
"." << _glx_version_minor
503 void glxGraphicsStateGuardian::
504 get_extra_extensions() {
505 save_extensions(glXQueryExtensionsString(_display, _screen));
518 void *glxGraphicsStateGuardian::
519 do_get_extension_func(
const char *name) {
520 nassertr(name != NULL, NULL);
522 if (glx_get_proc_address) {
526 #if defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESS) 532 return (
void *)glXGetProcAddress((
const GLubyte *)name);
534 #elif defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESSARB) 537 return (
void *)glXGetProcAddressARB((
const GLubyte *)name);
542 if (!_checked_get_proc_address) {
543 const char *funcName = NULL;
546 funcName =
"glXGetProcAddress";
548 }
else if (has_extension(
"GLX_ARB_get_proc_address")) {
549 funcName =
"glXGetProcAddressARB";
552 if (funcName != NULL) {
553 _glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)get_system_func(funcName);
554 if (_glXGetProcAddress == NULL) {
555 glxdisplay_cat.warning()
556 <<
"Couldn't load function " << funcName
557 <<
", GL extensions may be unavailable.\n";
561 _checked_get_proc_address =
true;
565 if (_glXGetProcAddress != NULL) {
566 return (
void *)_glXGetProcAddress((
const GLubyte *)name);
568 #endif // HAVE_GLXGETPROCADDRESS 572 return PosixGraphicsStateGuardian::do_get_extension_func(name);
580 void glxGraphicsStateGuardian::
581 query_glx_extensions() {
582 _supports_swap_control = has_extension(
"GLX_SGI_swap_control");
584 if (_supports_swap_control) {
585 _glXSwapIntervalSGI =
586 (PFNGLXSWAPINTERVALSGIPROC)get_extension_func(
"glXSwapIntervalSGI");
587 if (_glXSwapIntervalSGI == NULL) {
588 glxdisplay_cat.error()
589 <<
"Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
590 _supports_swap_control =
false;
594 if (_supports_swap_control) {
597 _glXSwapIntervalSGI(sync_video ? 1 : 0);
600 if (glx_support_fbconfig) {
603 _supports_fbconfig =
true;
606 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfig");
607 _glXCreateNewContext =
608 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateNewContext");
609 _glXGetVisualFromFBConfig =
610 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfig");
611 _glXGetFBConfigAttrib =
612 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttrib");
614 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreatePixmap");
616 if (_glXChooseFBConfig == NULL ||
617 _glXCreateNewContext == NULL ||
618 _glXGetVisualFromFBConfig == NULL ||
619 _glXGetFBConfigAttrib == NULL ||
620 _glXCreatePixmap == NULL) {
621 glxdisplay_cat.error()
622 <<
"Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
623 _supports_fbconfig =
false;
625 }
else if (has_extension(
"GLX_SGIX_fbconfig")) {
629 _supports_fbconfig =
true;
632 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfigSGIX");
633 _glXCreateNewContext =
634 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateContextWithConfigSGIX");
635 _glXGetVisualFromFBConfig =
636 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfigSGIX");
637 _glXGetFBConfigAttrib =
638 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttribSGIX");
640 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreateGLXPixmapWithConfigSGIX");
642 if (_glXChooseFBConfig == NULL ||
643 _glXCreateNewContext == NULL ||
644 _glXGetVisualFromFBConfig == NULL ||
645 _glXGetFBConfigAttrib == NULL ||
646 _glXCreatePixmap == NULL) {
647 glxdisplay_cat.error()
648 <<
"Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
649 _supports_fbconfig =
false;
655 _supports_pbuffer =
true;
656 _uses_sgix_pbuffer =
false;
659 (PFNGLXCREATEPBUFFERPROC)get_extension_func(
"glXCreatePbuffer");
660 _glXCreateGLXPbufferSGIX = NULL;
662 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyPbuffer");
663 if (_glXCreatePbuffer == NULL ||
664 _glXDestroyPbuffer == NULL) {
665 glxdisplay_cat.error()
666 <<
"Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
667 _supports_pbuffer =
false;
670 }
else if (has_extension(
"GLX_SGIX_pbuffer")) {
672 _uses_sgix_pbuffer =
true;
677 _glXCreatePbuffer = NULL;
678 _glXCreateGLXPbufferSGIX =
679 (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func(
"glXCreateGLXPbufferSGIX");
681 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyGLXPbufferSGIX");
682 if (_glXCreateGLXPbufferSGIX == NULL ||
683 _glXDestroyPbuffer == NULL) {
684 glxdisplay_cat.error()
685 <<
"Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
686 _supports_pbuffer =
false;
690 if (has_extension(
"GLX_ARB_create_context")) {
691 _glXCreateContextAttribs =
692 (PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func(
"glXCreateContextAttribsARB");
694 _glXCreateContextAttribs = NULL;
698 if (glxdisplay_cat.is_debug()) {
699 glxdisplay_cat.debug()
700 <<
"supports_swap_control = " << _supports_swap_control <<
"\n";
701 glxdisplay_cat.debug()
702 <<
"supports_fbconfig = " << _supports_fbconfig <<
"\n";
703 glxdisplay_cat.debug()
704 <<
"supports_pbuffer = " << _supports_pbuffer
705 <<
" sgix = " << _uses_sgix_pbuffer <<
"\n";
711 if (_gl_renderer.find(
"Mesa") != string::npos &&
712 _gl_renderer.find(
"Mesa DRI") == string::npos) {
714 _fbprops.set_force_software(1);
715 _fbprops.set_force_hardware(0);
717 _fbprops.set_force_hardware(1);
718 _fbprops.set_force_software(0);
728 void glxGraphicsStateGuardian::
729 show_glx_client_string(
const string &name,
int id) {
730 if (glgsg_cat.is_debug()) {
731 const char *text = glXGetClientString(_display,
id);
732 if (text == (
const char *)NULL) {
734 <<
"Unable to query " << name <<
" (client)\n";
737 << name <<
" (client) = " << (
const char *)text <<
"\n";
748 void glxGraphicsStateGuardian::
749 show_glx_server_string(
const string &name,
int id) {
750 if (glgsg_cat.is_debug()) {
751 const char *text = glXQueryServerString(_display, _screen,
id);
752 if (text == (
const char *)NULL) {
754 <<
"Unable to query " << name <<
" (server)\n";
757 << name <<
" (server) = " << (
const char *)text <<
"\n";
771 void glxGraphicsStateGuardian::
773 nassertv(_temp_context == (GLXContext)NULL);
775 int best_quality = 0;
780 if (_visuals != (XVisualInfo *)NULL) {
785 _visuals = XGetVisualInfo(_display, 0, 0, &nvisuals);
787 for (
int i = 0; i < nvisuals; i++) {
791 if (quality > best_quality) {
792 best_quality = quality;
794 best_props = fbprops;
799 if (best_quality > 0) {
800 _visual = _visuals + best_result;
801 _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE);
803 _fbprops = best_props;
808 glxdisplay_cat.error()
809 <<
"Could not find a usable pixel format.\n";
819 void glxGraphicsStateGuardian::
820 init_temp_context() {
822 DCAST_INTO_V(x11_pipe, get_pipe());
823 X11_Window root_window = x11_pipe->
get_root();
826 Visual *visual = _visual->visual;
827 nassertv(visual->c_class == DirectColor || visual->c_class == TrueColor);
828 _temp_colormap = XCreateColormap(_display, root_window,
830 XSetWindowAttributes wa;
831 wa.colormap = _temp_colormap;
832 unsigned long attrib_mask = CWColormap;
834 _temp_xwindow = XCreateWindow
835 (_display, root_window, 0, 0, 100, 100,
836 0, _visual->depth, InputOutput,
837 visual, attrib_mask, &wa);
838 if (_temp_xwindow == (X11_Window)NULL) {
839 glxdisplay_cat.error()
840 <<
"Could not create temporary window for context\n";
845 glXMakeCurrent(_display, _temp_xwindow, _temp_context);
847 get_extra_extensions();
848 query_glx_extensions();
857 void glxGraphicsStateGuardian::
858 destroy_temp_xwindow() {
859 glXMakeCurrent(_display, None, NULL);
861 if (_temp_colormap != (Colormap)NULL) {
862 XFreeColormap(_display, _temp_colormap);
863 _temp_colormap = (Colormap)NULL;
865 if (_temp_xwindow != (X11_Window)NULL) {
866 XDestroyWindow(_display, _temp_xwindow);
867 _temp_xwindow = (X11_Window)NULL;
870 if (_temp_context != (GLXContext)NULL) {
871 glXDestroyContext(_display, _temp_context);
872 _temp_context = (GLXContext)NULL;
This graphics pipe represents the interface for creating graphics windows on an X-based client...
A tiny specialization on GLGraphicsStateGuardian to add some glx-specific information.
void clear()
Unsets all properties that have been specified so far, and resets the FrameBufferProperties structure...
void choose_pixel_format(const FrameBufferProperties &properties, X11_Display *_display, int _screen, bool need_pbuffer, bool need_pixmap)
Selects a visual or fbconfig for all the windows and buffers that use this gsg.
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
This GSG is used only for CallbackGraphicsWindow (which might not be using the glx interfaces)...
bool glx_is_at_least_version(int major_version, int minor_version) const
Returns true if the runtime GLX version number is at least the indicated value, false otherwise...
An object to create GraphicsOutputs that share a particular 3-D API.
void get_properties(FrameBufferProperties &properties, XVisualInfo *visual)
Gets the FrameBufferProperties to match the indicated visual.
Similar to MutexHolder, but for a light reentrant mutex.
void get_properties_advanced(FrameBufferProperties &properties, bool &context_has_pbuffer, bool &pixmap_supported, bool &slow, GLXFBConfig config)
Gets the FrameBufferProperties to match the indicated GLXFBConfig.
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.
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.