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];
357 flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
359 if (gl_forward_compatible) {
360 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
361 if (gl_version.get_num_words() == 0 || gl_version[0] < 2) {
362 glxdisplay_cat.error()
363 <<
"gl-forward-compatible requires gl-version >= 3 0\n";
367 attrib_list[n++] = GLX_CONTEXT_FLAGS_ARB;
368 attrib_list[n++] = flags;
370 attrib_list[n] = None;
371 _context = _glXCreateContextAttribs(_display, _fbconfig, _share_context,
372 GL_TRUE, attrib_list);
375 _glXCreateNewContext(_display, _fbconfig, render_type, _share_context,
382 if (_visuals !=
nullptr) {
386 _visuals = _glXGetVisualFromFBConfig(_display, _fbconfig);
393 if (!properties.get_srgb_color()) {
394 _fbprops.set_srgb_color(
false);
397 if (glxdisplay_cat.is_debug()) {
398 glxdisplay_cat.debug()
399 <<
"Selected context " << best_result <<
": " << _fbprops <<
"\n";
400 glxdisplay_cat.debug()
401 <<
"context_has_pbuffer = " << _context_has_pbuffer
402 <<
", context_has_pixmap = " << _context_has_pixmap <<
"\n";
409 glxdisplay_cat.error()
410 <<
"Could not create FBConfig context!\n";
417 glxdisplay_cat.warning()
418 <<
"No suitable FBConfig contexts available; using XVisual only.\n"
421 _context = _temp_context;
422 _temp_context = (GLXContext)
nullptr;
426 _context_has_pixmap = !glXIsDirect(_display, _context);
429 _context_has_pbuffer =
false;
438 if (_glx_version_major < major_version) {
441 if (_glx_version_major > major_version) {
444 if (_glx_version_minor < minor_version) {
453 void glxGraphicsStateGuardian::
457 PosixGraphicsStateGuardian::gl_flush();
463 GLenum glxGraphicsStateGuardian::
464 gl_get_error()
const {
467 return PosixGraphicsStateGuardian::gl_get_error();
473 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
500 void glxGraphicsStateGuardian::
501 get_extra_extensions() {
503 save_extensions(glXQueryExtensionsString(_display, _screen));
512 void *glxGraphicsStateGuardian::
513 do_get_extension_func(
const char *name) {
514 nassertr(name !=
nullptr,
nullptr);
516 if (glx_get_proc_address) {
522 #if defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESS)
527 return (
void *)glXGetProcAddress((
const GLubyte *)name);
529 #elif defined(LINK_IN_GLXGETPROCADDRESS) && defined(HAVE_GLXGETPROCADDRESSARB)
532 return (
void *)glXGetProcAddressARB((
const GLubyte *)name);
537 if (!_checked_get_proc_address) {
538 const char *funcName =
nullptr;
541 funcName =
"glXGetProcAddress";
543 }
else if (has_extension(
"GLX_ARB_get_proc_address")) {
544 funcName =
"glXGetProcAddressARB";
547 if (funcName !=
nullptr) {
548 _glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)get_system_func(funcName);
549 if (_glXGetProcAddress ==
nullptr) {
550 glxdisplay_cat.warning()
551 <<
"Couldn't load function " << funcName
552 <<
", GL extensions may be unavailable.\n";
556 _checked_get_proc_address =
true;
560 if (_glXGetProcAddress !=
nullptr) {
561 return (
void *)_glXGetProcAddress((
const GLubyte *)name);
567 return PosixGraphicsStateGuardian::do_get_extension_func(name);
573 void glxGraphicsStateGuardian::
574 query_glx_extensions() {
575 _supports_swap_control = has_extension(
"GLX_SGI_swap_control");
577 if (_supports_swap_control) {
578 _glXSwapIntervalSGI =
579 (PFNGLXSWAPINTERVALSGIPROC)get_extension_func(
"glXSwapIntervalSGI");
580 if (_glXSwapIntervalSGI ==
nullptr) {
581 glxdisplay_cat.error()
582 <<
"Driver claims to support GLX_SGI_swap_control extension, but does not define all functions.\n";
583 _supports_swap_control =
false;
587 if (_supports_swap_control) {
590 _glXSwapIntervalSGI(sync_video ? 1 : 0);
593 if (glx_support_fbconfig) {
596 _supports_fbconfig =
true;
599 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfig");
600 _glXCreateNewContext =
601 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateNewContext");
602 _glXGetVisualFromFBConfig =
603 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfig");
604 _glXGetFBConfigAttrib =
605 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttrib");
607 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreatePixmap");
609 if (_glXChooseFBConfig ==
nullptr ||
610 _glXCreateNewContext ==
nullptr ||
611 _glXGetVisualFromFBConfig ==
nullptr ||
612 _glXGetFBConfigAttrib ==
nullptr ||
613 _glXCreatePixmap ==
nullptr) {
614 glxdisplay_cat.error()
615 <<
"Driver claims to support GLX_fbconfig extension, but does not define all functions.\n";
616 _supports_fbconfig =
false;
618 }
else if (has_extension(
"GLX_SGIX_fbconfig")) {
622 _supports_fbconfig =
true;
625 (PFNGLXCHOOSEFBCONFIGPROC)get_extension_func(
"glXChooseFBConfigSGIX");
626 _glXCreateNewContext =
627 (PFNGLXCREATENEWCONTEXTPROC)get_extension_func(
"glXCreateContextWithConfigSGIX");
628 _glXGetVisualFromFBConfig =
629 (PFNGLXGETVISUALFROMFBCONFIGPROC)get_extension_func(
"glXGetVisualFromFBConfigSGIX");
630 _glXGetFBConfigAttrib =
631 (PFNGLXGETFBCONFIGATTRIBPROC)get_extension_func(
"glXGetFBConfigAttribSGIX");
633 (PFNGLXCREATEPIXMAPPROC)get_extension_func(
"glXCreateGLXPixmapWithConfigSGIX");
635 if (_glXChooseFBConfig ==
nullptr ||
636 _glXCreateNewContext ==
nullptr ||
637 _glXGetVisualFromFBConfig ==
nullptr ||
638 _glXGetFBConfigAttrib ==
nullptr ||
639 _glXCreatePixmap ==
nullptr) {
640 glxdisplay_cat.error()
641 <<
"Driver claims to support GLX_SGIX_fbconfig extension, but does not define all functions.\n";
642 _supports_fbconfig =
false;
648 _supports_pbuffer =
true;
649 _uses_sgix_pbuffer =
false;
652 (PFNGLXCREATEPBUFFERPROC)get_extension_func(
"glXCreatePbuffer");
653 _glXCreateGLXPbufferSGIX =
nullptr;
655 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyPbuffer");
656 if (_glXCreatePbuffer ==
nullptr ||
657 _glXDestroyPbuffer ==
nullptr) {
658 glxdisplay_cat.error()
659 <<
"Driver claims to support GLX_pbuffer extension, but does not define all functions.\n";
660 _supports_pbuffer =
false;
663 }
else if (has_extension(
"GLX_SGIX_pbuffer")) {
665 _uses_sgix_pbuffer =
true;
670 _glXCreatePbuffer =
nullptr;
671 _glXCreateGLXPbufferSGIX =
672 (PFNGLXCREATEGLXPBUFFERSGIXPROC)get_extension_func(
"glXCreateGLXPbufferSGIX");
674 (PFNGLXDESTROYPBUFFERPROC)get_extension_func(
"glXDestroyGLXPbufferSGIX");
675 if (_glXCreateGLXPbufferSGIX ==
nullptr ||
676 _glXDestroyPbuffer ==
nullptr) {
677 glxdisplay_cat.error()
678 <<
"Driver claims to support GLX_SGIX_pbuffer extension, but does not define all functions.\n";
679 _supports_pbuffer =
false;
683 if (has_extension(
"GLX_ARB_create_context")) {
684 _glXCreateContextAttribs =
685 (PFNGLXCREATECONTEXTATTRIBSARBPROC)get_extension_func(
"glXCreateContextAttribsARB");
687 _glXCreateContextAttribs =
nullptr;
691 if (glxdisplay_cat.is_debug()) {
692 glxdisplay_cat.debug()
693 <<
"supports_swap_control = " << _supports_swap_control <<
"\n";
694 glxdisplay_cat.debug()
695 <<
"supports_fbconfig = " << _supports_fbconfig <<
"\n";
696 glxdisplay_cat.debug()
697 <<
"supports_pbuffer = " << _supports_pbuffer
698 <<
" sgix = " << _uses_sgix_pbuffer <<
"\n";
703 if (_gl_renderer.find(
"Mesa") != string::npos &&
704 _gl_renderer.find(
"Mesa DRI") == string::npos) {
706 _fbprops.set_force_software(1);
707 _fbprops.set_force_hardware(0);
709 _fbprops.set_force_hardware(1);
710 _fbprops.set_force_software(0);
717 void glxGraphicsStateGuardian::
718 show_glx_client_string(
const string &name,
int id) {
719 if (glgsg_cat.is_debug()) {
720 const char *text = glXGetClientString(_display,
id);
721 if (text ==
nullptr) {
723 <<
"Unable to query " << name <<
" (client)\n";
726 << name <<
" (client) = " << (
const char *)text <<
"\n";
734 void glxGraphicsStateGuardian::
735 show_glx_server_string(
const string &name,
int id) {
736 if (glgsg_cat.is_debug()) {
737 const char *text = glXQueryServerString(_display, _screen,
id);
738 if (text ==
nullptr) {
740 <<
"Unable to query " << name <<
" (server)\n";
743 << name <<
" (server) = " << (
const char *)text <<
"\n";
754 void glxGraphicsStateGuardian::
756 nassertv(_temp_context == (GLXContext)
nullptr);
758 int best_quality = 0;
763 if (_visuals !=
nullptr) {
768 _visuals = XGetVisualInfo(_display, 0,
nullptr, &nvisuals);
769 if (_visuals !=
nullptr) {
770 for (
int i = 0; i < nvisuals; i++) {
774 if (quality > best_quality) {
775 best_quality = quality;
777 best_props = fbprops;
782 if (best_quality > 0) {
783 _visual = _visuals + best_result;
784 _temp_context = glXCreateContext(_display, _visual, None, GL_TRUE);
786 _fbprops = best_props;
791 glxdisplay_cat.error()
792 <<
"Could not find a usable pixel format.\n";
799 void glxGraphicsStateGuardian::
800 init_temp_context() {
802 DCAST_INTO_V(x11_pipe, get_pipe());
803 X11_Window root_window = x11_pipe->
get_root();
806 Visual *visual = _visual->visual;
807 nassertv(visual->c_class == DirectColor || visual->c_class == TrueColor);
808 _temp_colormap = XCreateColormap(_display, root_window,
810 XSetWindowAttributes wa;
811 wa.colormap = _temp_colormap;
812 unsigned long attrib_mask = CWColormap;
814 _temp_xwindow = XCreateWindow
815 (_display, root_window, 0, 0, 100, 100,
816 0, _visual->depth, InputOutput,
817 visual, attrib_mask, &wa);
818 if (_temp_xwindow == (X11_Window)
nullptr) {
819 glxdisplay_cat.error()
820 <<
"Could not create temporary window for context\n";
825 glXMakeCurrent(_display, _temp_xwindow, _temp_context);
827 get_extra_extensions();
828 query_glx_extensions();
834 void glxGraphicsStateGuardian::
835 destroy_temp_xwindow() {
836 glXMakeCurrent(_display, None,
nullptr);
838 if (_temp_colormap != (Colormap)
nullptr) {
839 XFreeColormap(_display, _temp_colormap);
840 _temp_colormap = (Colormap)
nullptr;
842 if (_temp_xwindow != (X11_Window)
nullptr) {
843 XDestroyWindow(_display, _temp_xwindow);
844 _temp_xwindow = (X11_Window)
nullptr;
847 if (_temp_context != (GLXContext)
nullptr) {
848 glXDestroyContext(_display, _temp_context);
849 _temp_context = (GLXContext)
nullptr;
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
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 clear()
Unsets all properties that have been specified so far, and resets the FrameBufferProperties structure...
int get_quality(const FrameBufferProperties &reqs) const
Assumes that these properties are a description of a window.
This class is the main interface to controlling the render process.
An object to create GraphicsOutputs that share a particular 3-D API.
Similar to MutexHolder, but for a light reentrant mutex.
This GSG is used only for CallbackGraphicsWindow (which might not be using the glx interfaces),...
TypeHandle is the identifier used to differentiate C++ class types.
A tiny specialization on GLGraphicsStateGuardian to add some glx-specific information.
void get_properties(FrameBufferProperties &properties, XVisualInfo *visual)
Gets the FrameBufferProperties to match the indicated visual.
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.
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.
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.
This graphics pipe represents the interface for creating graphics windows on an X-based client.
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.