24 TypeHandle glxGraphicsStateGuardian::_type_handle;
29 glxGraphicsStateGuardian::
34 _share_context=
nullptr;
41 _context_has_pbuffer =
false;
42 _context_has_pixmap =
false;
45 _supports_swap_control =
false;
46 _supports_fbconfig =
false;
47 _supports_pbuffer =
false;
48 _uses_sgix_pbuffer =
false;
50 if (share_with !=
nullptr) {
51 _prepared_objects = share_with->get_prepared_objects();
52 _share_context = share_with->_context;
55 _checked_get_proc_address =
false;
56 _glXGetProcAddress =
nullptr;
57 _temp_context = (GLXContext)
nullptr;
58 _temp_xwindow = (X11_Window)
nullptr;
59 _temp_colormap = (Colormap)
nullptr;
65 glxGraphicsStateGuardian::
66 ~glxGraphicsStateGuardian() {
70 destroy_temp_xwindow();
71 if (_visuals !=
nullptr) {
74 if (_context != (GLXContext)
nullptr) {
75 glXDestroyContext(_display, _context);
76 _context = (GLXContext)
nullptr;
86 int use_gl, render_mode, double_buffer, stereo,
87 red_size, green_size, blue_size,
88 alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
89 depth_size, stencil_size;
91 glXGetConfig(_display, visual, GLX_USE_GL, &use_gl);
92 glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
93 glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
94 glXGetConfig(_display, visual, GLX_STEREO, &stereo);
95 glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
96 glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
97 glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
98 glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
99 glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
100 glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
101 glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
102 glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
103 glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
104 glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
116 properties.set_back_buffers(1);
119 properties.set_stereo(1);
122 properties.set_rgb_color(1);
124 properties.set_indexed_color(1);
127 properties.
set_rgba_bits(red_size, green_size, blue_size, alpha_size);
128 properties.set_stencil_bits(stencil_size);
129 properties.set_depth_bits(depth_size);
130 properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
133 properties.set_force_software(1);
134 properties.set_force_hardware(1);
142 bool &context_has_pbuffer,
bool &context_has_pixmap,
143 bool &slow, GLXFBConfig config) {
146 if (_supports_fbconfig) {
148 int render_type, double_buffer, stereo, red_size, green_size, blue_size,
149 alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
150 depth_size, stencil_size, samples, drawable_type, caveat, srgb_capable;
152 _glXGetFBConfigAttrib(_display, config, GLX_RENDER_TYPE, &render_type);
153 _glXGetFBConfigAttrib(_display, config, GLX_DOUBLEBUFFER, &double_buffer);
154 _glXGetFBConfigAttrib(_display, config, GLX_STEREO, &stereo);
155 _glXGetFBConfigAttrib(_display, config, GLX_RED_SIZE, &red_size);
156 _glXGetFBConfigAttrib(_display, config, GLX_GREEN_SIZE, &green_size);
157 _glXGetFBConfigAttrib(_display, config, GLX_BLUE_SIZE, &blue_size);
158 _glXGetFBConfigAttrib(_display, config, GLX_ALPHA_SIZE, &alpha_size);
159 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_RED_SIZE, &ared_size);
160 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_GREEN_SIZE, &agreen_size);
161 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_BLUE_SIZE, &ablue_size);
162 _glXGetFBConfigAttrib(_display, config, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
163 _glXGetFBConfigAttrib(_display, config, GLX_DEPTH_SIZE, &depth_size);
164 _glXGetFBConfigAttrib(_display, config, GLX_STENCIL_SIZE, &stencil_size);
165 _glXGetFBConfigAttrib(_display, config, GLX_SAMPLES, &samples);
166 _glXGetFBConfigAttrib(_display, config, GLX_DRAWABLE_TYPE, &drawable_type);
167 _glXGetFBConfigAttrib(_display, config, GLX_CONFIG_CAVEAT, &caveat);
168 _glXGetFBConfigAttrib(_display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable);
170 context_has_pbuffer =
false;
171 if ((drawable_type & GLX_PBUFFER_BIT)!=0) {
172 context_has_pbuffer =
true;
175 context_has_pixmap =
false;
176 if ((drawable_type & GLX_PIXMAP_BIT)!=0) {
177 context_has_pixmap =
true;
181 if (caveat == GLX_SLOW_CONFIG) {
185 if ((drawable_type & GLX_WINDOW_BIT)==0) {
191 properties.set_back_buffers(1);
195 properties.set_stereo(
true);
199 properties.set_srgb_color(
true);
202 if ((render_type & GLX_RGBA_BIT)!=0) {
203 properties.set_rgb_color(
true);
205 if ((render_type & GLX_COLOR_INDEX_BIT)!=0) {
206 properties.set_indexed_color(
true);
209 properties.
set_rgba_bits(red_size, green_size, blue_size, alpha_size);
210 properties.set_stencil_bits(stencil_size);
211 properties.set_depth_bits(depth_size);
212 properties.set_accum_bits(ared_size+agreen_size+ablue_size+aalpha_size);
213 properties.set_multisamples(samples);
216 properties.set_force_software(1);
217 properties.set_force_hardware(1);
227 X11_Display *display,
228 int screen,
bool need_pbuffer,
bool need_pixmap) {
236 if (_visuals !=
nullptr) {
246 destroy_temp_xwindow();
247 choose_temp_visual(properties);
248 if (_temp_context ==
nullptr) {
258 if (!_supports_fbconfig) {
261 glxdisplay_cat.debug()
262 <<
" No FBConfig supported; using XVisual only.\n" 265 _context = _temp_context;
266 _temp_context = (GLXContext)
nullptr;
270 _context_has_pixmap = !glXIsDirect(_display, _context);
273 _context_has_pbuffer =
false;
282 int best_quality = 0;
286 int render_type = GLX_RGBA_TYPE;
287 if (properties.get_indexed_color()) {
288 render_type = GLX_COLOR_INDEX_TYPE;
291 static const int max_attrib_list = 32;
292 int attrib_list[max_attrib_list];
294 attrib_list[n++] = GLX_STEREO;
295 attrib_list[n++] = GLX_DONT_CARE;
296 attrib_list[n++] = GLX_RENDER_TYPE;
297 attrib_list[n++] = GLX_DONT_CARE;
298 attrib_list[n++] = GLX_DRAWABLE_TYPE;
299 attrib_list[n++] = GLX_DONT_CARE;
300 attrib_list[n] = (int)None;
303 GLXFBConfig *configs =
304 _glXChooseFBConfig(_display, _screen, attrib_list, &num_configs);
306 if (configs !=
nullptr) {
307 bool context_has_pbuffer, context_has_pixmap, slow;
309 for (i = 0; i < num_configs; ++i) {
314 if ((quality > 0)&&(slow)) quality -= 10000000;
315 if (glxdisplay_cat.is_debug()) {
316 const char *pbuffertext = context_has_pbuffer ?
" (pbuffer)" :
"";
317 const char *pixmaptext = context_has_pixmap ?
" (pixmap)" :
"";
318 const char *slowtext = slow ?
" (slow)" :
"";
319 glxdisplay_cat.debug()
320 << i <<
": " << fbprops <<
" quality=" << quality << pbuffertext
321 << pixmaptext << slowtext <<
"\n";
323 if (need_pbuffer && !context_has_pbuffer) {
326 if (need_pixmap && !context_has_pixmap) {
330 if (quality > best_quality) {
331 best_quality = quality;
333 best_props = fbprops;
338 if (best_quality > 0) {
339 _fbconfig = configs[best_result];
341 if (_glXCreateContextAttribs !=
nullptr) {
345 attrib_list[n++] = GLX_RENDER_TYPE;
346 attrib_list[n++] = render_type;
347 if (gl_version.get_num_words() > 0) {
348 attrib_list[n++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
349 attrib_list[n++] = gl_version[0];
350 if (gl_version.get_num_words() > 1) {
351 attrib_list[n++] = GLX_CONTEXT_MINOR_VERSION_ARB;
352 attrib_list[n++] = gl_version[1];
356 attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB;
357 attrib_list[n++] = GLX_CONTEXT_DEBUG_BIT_ARB;
359 attrib_list[n] = None;
360 _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context,
361 GL_TRUE, attrib_list);
364 _glXCreateNewContext(_display, _fbconfig, render_type, _share_context,
371 if (_visuals !=
nullptr) {
375 _visuals = _glXGetVisualFromFBConfig(_display, _fbconfig);
382 if (!properties.get_srgb_color()) {
383 _fbprops.set_srgb_color(
false);
386 if (glxdisplay_cat.is_debug()) {
387 glxdisplay_cat.debug()
388 <<
"Selected context " << best_result <<
": " << _fbprops <<
"\n";
389 glxdisplay_cat.debug()
390 <<
"context_has_pbuffer = " << _context_has_pbuffer
391 <<
", context_has_pixmap = " << _context_has_pixmap <<
"\n";
398 glxdisplay_cat.error()
399 <<
"Could not create FBConfig context!\n";
406 glxdisplay_cat.warning()
407 <<
"No suitable FBConfig contexts available; using XVisual only.\n" 410 _context = _temp_context;
411 _temp_context = (GLXContext)
nullptr;
415 _context_has_pixmap = !glXIsDirect(_display, _context);
418 _context_has_pbuffer =
false;
427 if (_glx_version_major < major_version) {
430 if (_glx_version_major > major_version) {
433 if (_glx_version_minor < minor_version) {
442 void glxGraphicsStateGuardian::
446 PosixGraphicsStateGuardian::gl_flush();
452 GLenum glxGraphicsStateGuardian::
453 gl_get_error()
const {
456 return PosixGraphicsStateGuardian::gl_get_error();
462 void glxGraphicsStateGuardian::
465 PosixGraphicsStateGuardian::query_gl_version();
467 show_glx_client_string(
"GLX_VENDOR", GLX_VENDOR);
468 show_glx_client_string(
"GLX_VERSION", GLX_VERSION);
469 show_glx_server_string(
"GLX_VENDOR", GLX_VENDOR);
470 show_glx_server_string(
"GLX_VERSION", GLX_VERSION);
472 glXQueryVersion(_display, &_glx_version_major, &_glx_version_minor);
477 if (glgsg_cat.is_debug()) {
479 <<
"GLX_VERSION = " << _glx_version_major <<
"." << _glx_version_minor
489 void glxGraphicsStateGuardian::
490 get_extra_extensions() {
492 save_extensions(glXQueryExtensionsString(_display, _screen));
501 void *glxGraphicsStateGuardian::
502 do_get_extension_func(
const char *name) {
503 nassertr(name !=
nullptr,
nullptr);
505 if (glx_get_proc_address) {
511 #if defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESS) 516 return (
void *)glXGetProcAddress((
const GLubyte *)name);
518 #elif defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESSARB) 521 return (
void *)glXGetProcAddressARB((
const GLubyte *)name);
526 if (!_checked_get_proc_address) {
527 const char *funcName =
nullptr;
530 funcName =
"glXGetProcAddress";
532 }
else if (has_extension(
"GLX_ARB_get_proc_address")) {
533 funcName =
"glXGetProcAddressARB";
536 if (funcName !=
nullptr) {
537 _glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)get_system_func(funcName);
538 if (_glXGetProcAddress ==
nullptr) {
539 glxdisplay_cat.warning()
540 <<
"Couldn't load function " << funcName
541 <<
", GL extensions may be unavailable.\n";
545 _checked_get_proc_address =
true;
549 if (_glXGetProcAddress !=
nullptr) {
550 return (
void *)_glXGetProcAddress((
const GLubyte *)name);
552 #endif // HAVE_GLXGETPROCADDRESS 556 return PosixGraphicsStateGuardian::do_get_extension_func(name);
562 void glxGraphicsStateGuardian::
563 query_glx_extensions() {
564 _supports_swap_control = has_extension(
"GLX_SGI_swap_control");
566 if (_supports_swap_control) {
567 _glXSwapIntervalSGI =
568 (PFNGLXSWAPINTERVALSGIPROC)get_extension_func(
"glXSwapIntervalSGI");
569 if (_glXSwapIntervalSGI ==
nullptr) {
570 glxdisplay_cat.error()
571 <<
"Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
572 _supports_swap_control =
false;
576 if (_supports_swap_control) {
579 _glXSwapIntervalSGI(sync_video ? 1 : 0);
582 if (glx_support_fbconfig) {
585 _supports_fbconfig =
true;
588 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfig");
589 _glXCreateNewContext =
590 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateNewContext");
591 _glXGetVisualFromFBConfig =
592 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfig");
593 _glXGetFBConfigAttrib =
594 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttrib");
596 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreatePixmap");
598 if (_glXChooseFBConfig ==
nullptr ||
599 _glXCreateNewContext ==
nullptr ||
600 _glXGetVisualFromFBConfig ==
nullptr ||
601 _glXGetFBConfigAttrib ==
nullptr ||
602 _glXCreatePixmap ==
nullptr) {
603 glxdisplay_cat.error()
604 <<
"Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
605 _supports_fbconfig =
false;
607 }
else if (has_extension(
"GLX_SGIX_fbconfig")) {
611 _supports_fbconfig =
true;
614 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfigSGIX");
615 _glXCreateNewContext =
616 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateContextWithConfigSGIX");
617 _glXGetVisualFromFBConfig =
618 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfigSGIX");
619 _glXGetFBConfigAttrib =
620 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttribSGIX");
622 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreateGLXPixmapWithConfigSGIX");
624 if (_glXChooseFBConfig ==
nullptr ||
625 _glXCreateNewContext ==
nullptr ||
626 _glXGetVisualFromFBConfig ==
nullptr ||
627 _glXGetFBConfigAttrib ==
nullptr ||
628 _glXCreatePixmap ==
nullptr) {
629 glxdisplay_cat.error()
630 <<
"Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
631 _supports_fbconfig =
false;
637 _supports_pbuffer =
true;
638 _uses_sgix_pbuffer =
false;
641 (PFNGLXCREATEPBUFFERPROC)get_extension_func(
"glXCreatePbuffer");
642 _glXCreateGLXPbufferSGIX =
nullptr;
644 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyPbuffer");
645 if (_glXCreatePbuffer ==
nullptr ||
646 _glXDestroyPbuffer ==
nullptr) {
647 glxdisplay_cat.error()
648 <<
"Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
649 _supports_pbuffer =
false;
652 }
else if (has_extension(
"GLX_SGIX_pbuffer")) {
654 _uses_sgix_pbuffer =
true;
659 _glXCreatePbuffer =
nullptr;
660 _glXCreateGLXPbufferSGIX =
661 (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func(
"glXCreateGLXPbufferSGIX");
663 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyGLXPbufferSGIX");
664 if (_glXCreateGLXPbufferSGIX ==
nullptr ||
665 _glXDestroyPbuffer ==
nullptr) {
666 glxdisplay_cat.error()
667 <<
"Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
668 _supports_pbuffer =
false;
672 if (has_extension(
"GLX_ARB_create_context")) {
673 _glXCreateContextAttribs =
674 (PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func(
"glXCreateContextAttribsARB");
676 _glXCreateContextAttribs =
nullptr;
680 if (glxdisplay_cat.is_debug()) {
681 glxdisplay_cat.debug()
682 <<
"supports_swap_control = " << _supports_swap_control <<
"\n";
683 glxdisplay_cat.debug()
684 <<
"supports_fbconfig = " << _supports_fbconfig <<
"\n";
685 glxdisplay_cat.debug()
686 <<
"supports_pbuffer = " << _supports_pbuffer
687 <<
" sgix = " << _uses_sgix_pbuffer <<
"\n";
692 if (_gl_renderer.find(
"Mesa") != string::npos &&
693 _gl_renderer.find(
"Mesa DRI") == string::npos) {
695 _fbprops.set_force_software(1);
696 _fbprops.set_force_hardware(0);
698 _fbprops.set_force_hardware(1);
699 _fbprops.set_force_software(0);
706 void glxGraphicsStateGuardian::
707 show_glx_client_string(
const string &name,
int id) {
708 if (glgsg_cat.is_debug()) {
709 const char *text = glXGetClientString(_display,
id);
710 if (text ==
nullptr) {
712 <<
"Unable to query " << name <<
" (client)\n";
715 << name <<
" (client) = " << (
const char *)text <<
"\n";
723 void glxGraphicsStateGuardian::
724 show_glx_server_string(
const string &name,
int id) {
725 if (glgsg_cat.is_debug()) {
726 const char *text = glXQueryServerString(_display, _screen,
id);
727 if (text ==
nullptr) {
729 <<
"Unable to query " << name <<
" (server)\n";
732 << name <<
" (server) = " << (
const char *)text <<
"\n";
743 void glxGraphicsStateGuardian::
745 nassertv(_temp_context == (GLXContext)
nullptr);
747 int best_quality = 0;
752 if (_visuals !=
nullptr) {
757 _visuals = XGetVisualInfo(_display, 0,
nullptr, &nvisuals);
758 if (_visuals !=
nullptr) {
759 for (
int i = 0; i < nvisuals; i++) {
763 if (quality > best_quality) {
764 best_quality = quality;
766 best_props = fbprops;
771 if (best_quality > 0) {
772 _visual = _visuals + best_result;
773 _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE);
775 _fbprops = best_props;
780 glxdisplay_cat.error()
781 <<
"Could not find a usable pixel format.\n";
788 void glxGraphicsStateGuardian::
789 init_temp_context() {
791 DCAST_INTO_V(x11_pipe, get_pipe());
792 X11_Window root_window = x11_pipe->
get_root();
795 Visual *visual = _visual->visual;
796 nassertv(visual->c_class == DirectColor || visual->c_class == TrueColor);
797 _temp_colormap = XCreateColormap(_display, root_window,
799 XSetWindowAttributes wa;
800 wa.colormap = _temp_colormap;
801 unsigned long attrib_mask = CWColormap;
803 _temp_xwindow = XCreateWindow
804 (_display, root_window, 0, 0, 100, 100,
805 0, _visual->depth, InputOutput,
806 visual, attrib_mask, &wa);
807 if (_temp_xwindow == (X11_Window)
nullptr) {
808 glxdisplay_cat.error()
809 <<
"Could not create temporary window for context\n";
814 glXMakeCurrent(_display, _temp_xwindow, _temp_context);
816 get_extra_extensions();
817 query_glx_extensions();
823 void glxGraphicsStateGuardian::
824 destroy_temp_xwindow() {
825 glXMakeCurrent(_display, None,
nullptr);
827 if (_temp_colormap != (Colormap)
nullptr) {
828 XFreeColormap(_display, _temp_colormap);
829 _temp_colormap = (Colormap)
nullptr;
831 if (_temp_xwindow != (X11_Window)
nullptr) {
832 XDestroyWindow(_display, _temp_xwindow);
833 _temp_xwindow = (X11_Window)
nullptr;
836 if (_temp_context != (GLXContext)
nullptr) {
837 glXDestroyContext(_display, _temp_context);
838 _temp_context = (GLXContext)
nullptr;
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.