|
|
@@ -167,109 +167,6 @@ pipe_constructor() {
|
|
|
return new glxGraphicsPipe;
|
|
|
}
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: glxGraphicsPipe::make_gsg
|
|
|
-// Access: Protected, Virtual
|
|
|
-// Description: Creates a new GSG to use the pipe (but no windows
|
|
|
-// have been created yet for the GSG). This method will
|
|
|
-// be called in the draw thread for the GSG.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-PT(GraphicsStateGuardian) glxGraphicsPipe::
|
|
|
-make_gsg(const FrameBufferProperties &properties,
|
|
|
- GraphicsStateGuardian *share_with) {
|
|
|
- if (!_is_valid) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- glxGraphicsStateGuardian *share_gsg = NULL;
|
|
|
- GLXContext share_context = NULL;
|
|
|
-
|
|
|
- if (share_with != (GraphicsStateGuardian *)NULL) {
|
|
|
- if (!share_with->is_exact_type(glxGraphicsStateGuardian::get_class_type())) {
|
|
|
- glxdisplay_cat.error()
|
|
|
- << "Cannot share context between glxGraphicsStateGuardian and "
|
|
|
- << share_with->get_type() << "\n";
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- DCAST_INTO_R(share_gsg, share_with, NULL);
|
|
|
- share_context = share_gsg->_context;
|
|
|
- }
|
|
|
-
|
|
|
- // There's no interface in GLX to query whether we have a software
|
|
|
- // or a hardware rendering context. Fortunately, there seems to be
|
|
|
- // only one likely software GLX context, and that's Mesa; we will
|
|
|
- // assume that any Mesa GLX context is software-based, and any other
|
|
|
- // context is hardware-based.
|
|
|
-
|
|
|
- // Unforunately, to determine whether we are using Mesa, we need to
|
|
|
- // create a GL context, bind it to a window, and then examine the
|
|
|
- // GL_RENDERER string to see if it contains "Mesa". So we must
|
|
|
- // create the GSG and its window first, and wait until the GSG has
|
|
|
- // been reset, before we can ask this question. Therefore we don't
|
|
|
- // deal with hardware/software at this point, but rather in
|
|
|
- // glxGraphicsStateGuardian::reset().
|
|
|
-
|
|
|
- // We do, however, need to determine ahead of time whether the user
|
|
|
- // would prefer a hardware or software context.
|
|
|
- int frame_buffer_mode = properties.get_frame_buffer_mode();
|
|
|
- int want_hardware = (frame_buffer_mode & (FrameBufferProperties::FM_hardware |
|
|
|
- FrameBufferProperties::FM_software));
|
|
|
-
|
|
|
- FrameBufferProperties new_properties = properties;
|
|
|
- GLXContext context = NULL;
|
|
|
- XVisualInfo *visual = NULL;
|
|
|
-
|
|
|
-#ifdef HAVE_GLXFBCONFIG
|
|
|
- GLXFBConfig fbconfig = choose_fbconfig(new_properties);
|
|
|
- if (fbconfig != None) {
|
|
|
- context =
|
|
|
- glXCreateNewContext(_display, fbconfig, GLX_RGBA_TYPE, share_context,
|
|
|
- GL_TRUE);
|
|
|
- if (context == NULL) {
|
|
|
- fbconfig = None;
|
|
|
- }
|
|
|
- }
|
|
|
-#endif // HAVE_GLXFBCONFIG
|
|
|
-
|
|
|
- if (context == NULL) {
|
|
|
- // If we couldn't create a context with the fbconfig interface,
|
|
|
- // try falling back to the older XVisual interface.
|
|
|
- visual = choose_visual(new_properties);
|
|
|
-
|
|
|
- if (visual != (XVisualInfo *)NULL) {
|
|
|
- context = glXCreateContext(_display, visual, None, GL_TRUE);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (context == NULL) {
|
|
|
- glxdisplay_cat.error()
|
|
|
- << "Could not create GL context.\n";
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef HAVE_GLXFBCONFIG
|
|
|
- if (visual == (XVisualInfo *)NULL) {
|
|
|
- // If we used the fbconfig to open the context, we still need to
|
|
|
- // get the associated XVisual.
|
|
|
- nassertr(fbconfig != None, NULL);
|
|
|
- visual = glXGetVisualFromFBConfig(_display, fbconfig);
|
|
|
- }
|
|
|
-
|
|
|
- // Now we can make a GSG.
|
|
|
- PT(glxGraphicsStateGuardian) gsg =
|
|
|
- new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware,
|
|
|
- context, visual, _display, _screen, fbconfig);
|
|
|
-
|
|
|
-#else
|
|
|
- PT(glxGraphicsStateGuardian) gsg =
|
|
|
- new glxGraphicsStateGuardian(new_properties, share_gsg, want_hardware,
|
|
|
- context, visual, _display, _screen);
|
|
|
-#endif // HAVE_GLXFBCONFIG
|
|
|
-
|
|
|
- return gsg.p();
|
|
|
-}
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: glxGraphicsPipe::make_output
|
|
|
// Access: Protected, Virtual
|
|
|
@@ -288,14 +185,11 @@ make_output(const string &name,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- // This pipe is not yet capable of creating nonhomogeneous windows.
|
|
|
- if (properties != gsg->get_default_properties()) {
|
|
|
- return NULL;
|
|
|
+ glxGraphicsStateGuardian *glxgsg = 0;
|
|
|
+ if (gsg != 0) {
|
|
|
+ DCAST_INTO_R(glxgsg, gsg, NULL);
|
|
|
}
|
|
|
-
|
|
|
- glxGraphicsStateGuardian *glxgsg;
|
|
|
- DCAST_INTO_R(glxgsg, gsg, NULL);
|
|
|
-
|
|
|
+
|
|
|
// First thing to try: a glxGraphicsWindow
|
|
|
|
|
|
if (retry == 0) {
|
|
|
@@ -311,22 +205,39 @@ make_output(const string &name,
|
|
|
x_size, y_size, flags, gsg, host);
|
|
|
}
|
|
|
|
|
|
- // // Second thing to try: a glGraphicsBuffer
|
|
|
- //
|
|
|
- // if (retry == 1) {
|
|
|
- // if ((!support_render_texture)||
|
|
|
- // ((flags&BF_require_parasite)!=0)||
|
|
|
- // ((flags&BF_require_window)!=0)) {
|
|
|
- // return NULL;
|
|
|
- // }
|
|
|
- // if (precertify) {
|
|
|
- // if (!glxgsg->_supports_framebuffer_object) {
|
|
|
- // return NULL;
|
|
|
- // }
|
|
|
- // }
|
|
|
- // return new glGraphicsBuffer(this, name, properties,
|
|
|
- // x_size, y_size, flags, gsg, host);
|
|
|
- // }
|
|
|
+ // Second thing to try: a GLGraphicsBuffer
|
|
|
+
|
|
|
+ if (retry == 1) {
|
|
|
+ if ((!support_render_texture)||
|
|
|
+ // (!gl_support_fbo)||
|
|
|
+ (host==0)||
|
|
|
+ ((flags&BF_require_parasite)!=0)||
|
|
|
+ ((flags&BF_require_window)!=0)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ // Early failure - if we are sure that this buffer WONT
|
|
|
+ // meet specs, we can bail out early.
|
|
|
+ if ((flags & BF_fb_props_optional)==0) {
|
|
|
+ if ((properties.get_indexed_color() > 0)||
|
|
|
+ (properties.get_back_buffers() > 0)||
|
|
|
+ (properties.get_accum_bits() > 0)||
|
|
|
+ (properties.get_multisamples() > 0)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Early success - if we are sure that this buffer WILL
|
|
|
+ // meet specs, we can precertify it.
|
|
|
+ if ((glxgsg != 0) &&
|
|
|
+ (glxgsg->is_valid()) &&
|
|
|
+ (!glxgsg->needs_reset()) &&
|
|
|
+ (glxgsg->_supports_framebuffer_object) &&
|
|
|
+ (glxgsg->_glDrawBuffers != 0)&&
|
|
|
+ (properties.is_basic())) {
|
|
|
+ precertify = true;
|
|
|
+ }
|
|
|
+ return new GLGraphicsBuffer(this, name, properties,
|
|
|
+ x_size, y_size, flags, gsg, host);
|
|
|
+ }
|
|
|
|
|
|
#ifdef HAVE_GLXFBCONFIG
|
|
|
// Third thing to try: a glxGraphicsBuffer
|
|
|
@@ -349,608 +260,6 @@ make_output(const string &name,
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-#ifdef HAVE_GLXFBCONFIG
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: glxGraphicsPipe::choose_fbconfig
|
|
|
-// Access: Private
|
|
|
-// Description: Selects an appropriate GLXFBConfig for the given
|
|
|
-// frame buffer properties. Returns the selected
|
|
|
-// fbconfig if successful, or None otherwise.
|
|
|
-//
|
|
|
-// If successful, this may modify properties to reflect
|
|
|
-// the actual visual chosen.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-GLXFBConfig glxGraphicsPipe::
|
|
|
-choose_fbconfig(FrameBufferProperties &properties) const {
|
|
|
- int frame_buffer_mode = 0;
|
|
|
- if (properties.has_frame_buffer_mode()) {
|
|
|
- frame_buffer_mode = properties.get_frame_buffer_mode();
|
|
|
- }
|
|
|
-
|
|
|
- int want_depth_bits = properties.get_depth_bits();
|
|
|
- int want_color_bits = properties.get_color_bits();
|
|
|
- int want_alpha_bits = properties.get_alpha_bits();
|
|
|
- int want_stencil_bits = properties.get_stencil_bits();
|
|
|
- int want_multisamples = properties.get_multisamples();
|
|
|
-
|
|
|
- GLXFBConfig fbconfig =
|
|
|
- try_for_fbconfig(frame_buffer_mode, want_depth_bits, want_color_bits,
|
|
|
- want_alpha_bits, want_stencil_bits, want_multisamples);
|
|
|
-
|
|
|
- if (fbconfig == None) {
|
|
|
- glxdisplay_cat.info()
|
|
|
- << "glxGraphicsPipe::choose_fbconfig() - fbconfig with requested "
|
|
|
- << "capabilities not found; trying for lesser fbconfig.\n";
|
|
|
-
|
|
|
- bool special_size_request =
|
|
|
- (want_depth_bits != 1 || want_color_bits != 1);
|
|
|
-
|
|
|
- // We try to be smart about choosing a close match for the fbconfig.
|
|
|
- // First, we'll eliminate some of the more esoteric options one at
|
|
|
- // a time, then two at a time, and finally we'll try just the bare
|
|
|
- // minimum.
|
|
|
-
|
|
|
- if (special_size_request) {
|
|
|
- // Actually, first we'll eliminate all of the minimum sizes, to
|
|
|
- // try to open a window with all of the requested options, but
|
|
|
- // maybe not as many bits in some options as we'd like.
|
|
|
- fbconfig = try_for_fbconfig(frame_buffer_mode);
|
|
|
- }
|
|
|
-
|
|
|
- if (fbconfig == None) {
|
|
|
- // Ok, not good enough. Now try to eliminate options, but keep
|
|
|
- // as many bits as we asked for.
|
|
|
-
|
|
|
- pset<int> tried_masks;
|
|
|
- tried_masks.insert(frame_buffer_mode);
|
|
|
-
|
|
|
- int i;
|
|
|
- for (i = 0; fbconfig == None && strip_properties[i] != 0; i++) {
|
|
|
- int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
|
|
|
- if (tried_masks.insert(new_frame_buffer_mode).second) {
|
|
|
- fbconfig = try_for_fbconfig(new_frame_buffer_mode, want_depth_bits,
|
|
|
- want_color_bits, want_alpha_bits,
|
|
|
- want_stencil_bits, want_multisamples);
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (special_size_request) {
|
|
|
- tried_masks.clear();
|
|
|
- tried_masks.insert(frame_buffer_mode);
|
|
|
-
|
|
|
- if (fbconfig == None) {
|
|
|
- // Try once more, this time eliminating all of the size
|
|
|
- // requests.
|
|
|
- for (i = 0; fbconfig == None && strip_properties[i] != 0; i++) {
|
|
|
- int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
|
|
|
- if (tried_masks.insert(new_frame_buffer_mode).second) {
|
|
|
- fbconfig = try_for_fbconfig(new_frame_buffer_mode);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (fbconfig == None) {
|
|
|
- // Here's our last-ditch desparation attempt: give us any GLX
|
|
|
- // fbconfig at all!
|
|
|
- fbconfig = try_for_fbconfig(0);
|
|
|
- }
|
|
|
-
|
|
|
- if (fbconfig == None) {
|
|
|
- // This is only an info message, because we can still fall
|
|
|
- // back to the XVisual interface.
|
|
|
- glxdisplay_cat.info()
|
|
|
- << "Could not get any GLX fbconfig.\n";
|
|
|
- return None;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- glxdisplay_cat.info()
|
|
|
- << "Selected suitable GLX fbconfig.\n";
|
|
|
-
|
|
|
- // Now update our framebuffer_mode and bit depth appropriately.
|
|
|
- int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
|
|
|
- alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
|
|
|
- depth_size, stencil_size, samples;
|
|
|
-
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &render_mode);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_DOUBLEBUFFER, &double_buffer);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_STEREO, &stereo);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_RED_SIZE, &red_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_GREEN_SIZE, &green_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_BLUE_SIZE, &blue_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_ALPHA_SIZE, &alpha_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_RED_SIZE, &ared_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_GREEN_SIZE, &agreen_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_BLUE_SIZE, &ablue_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_DEPTH_SIZE, &depth_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_STENCIL_SIZE, &stencil_size);
|
|
|
- glXGetFBConfigAttrib(_display, fbconfig, GLX_SAMPLES, &samples);
|
|
|
-
|
|
|
- frame_buffer_mode = 0;
|
|
|
- if (double_buffer) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
|
|
|
- }
|
|
|
- if (stereo) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_stereo;
|
|
|
- }
|
|
|
- if (!render_mode) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_index;
|
|
|
- }
|
|
|
- if (stencil_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_stencil;
|
|
|
- }
|
|
|
- if (depth_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_depth;
|
|
|
- }
|
|
|
- if (alpha_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_alpha;
|
|
|
- }
|
|
|
- if (ared_size + agreen_size + ablue_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_accum;
|
|
|
- }
|
|
|
- if (samples != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_multisample;
|
|
|
- }
|
|
|
-
|
|
|
- properties.set_frame_buffer_mode(frame_buffer_mode);
|
|
|
- properties.set_color_bits(red_size + green_size + blue_size);
|
|
|
- properties.set_alpha_bits(alpha_size);
|
|
|
- properties.set_depth_bits(depth_size);
|
|
|
- properties.set_stencil_bits(stencil_size);
|
|
|
- properties.set_multisamples(samples);
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug()
|
|
|
- << "GLX Fbconfig Info (# bits of each):" << endl
|
|
|
- << " RGBA: " << red_size << " " << green_size << " " << blue_size
|
|
|
- << " " << alpha_size << endl
|
|
|
- << " Accum RGBA: " << ared_size << " " << agreen_size << " "
|
|
|
- << ablue_size << " " << aalpha_size << endl
|
|
|
- << " Depth: " << depth_size << endl
|
|
|
- << " Stencil: " << stencil_size << endl
|
|
|
- << " Samples: " << samples << endl
|
|
|
- << " DoubleBuffer? " << double_buffer << endl
|
|
|
- << " Stereo? " << stereo << endl;
|
|
|
- }
|
|
|
-
|
|
|
- return fbconfig;
|
|
|
-}
|
|
|
-#endif // HAVE_GLXFBCONFIG
|
|
|
-
|
|
|
-#ifdef HAVE_GLXFBCONFIG
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: glxGraphicsPipe::try_for_fbconfig
|
|
|
-// Access: Private
|
|
|
-// Description: Attempt to get the requested fbconfig, if it is
|
|
|
-// available. It's just a wrapper around
|
|
|
-// glXChooseFBConfig(). It returns the fbconfig
|
|
|
-// information if possible, or None if it is not.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-GLXFBConfig glxGraphicsPipe::
|
|
|
-try_for_fbconfig(int framebuffer_mode,
|
|
|
- int want_depth_bits, int want_color_bits,
|
|
|
- int want_alpha_bits, int want_stencil_bits,
|
|
|
- int want_multisamples) const {
|
|
|
- static const int max_attrib_list = 32;
|
|
|
- int attrib_list[max_attrib_list];
|
|
|
- int n=0;
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug()
|
|
|
- << "Trying for fbconfig with: RGB(" << want_color_bits << ")";
|
|
|
- }
|
|
|
-
|
|
|
- int want_color_component_bits = max(want_color_bits / 3, 1);
|
|
|
-
|
|
|
- attrib_list[n++] = GLX_RED_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_GREEN_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_BLUE_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " ALPHA(" << want_alpha_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_ALPHA_SIZE;
|
|
|
- attrib_list[n++] = want_alpha_bits;
|
|
|
- }
|
|
|
-
|
|
|
- switch (framebuffer_mode & FrameBufferProperties::FM_buffer) {
|
|
|
- case FrameBufferProperties::FM_single_buffer:
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " SINGLEBUFFER";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_DOUBLEBUFFER;
|
|
|
- attrib_list[n++] = false;
|
|
|
- break;
|
|
|
-
|
|
|
- case FrameBufferProperties::FM_double_buffer:
|
|
|
- case FrameBufferProperties::FM_triple_buffer:
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_DOUBLEBUFFER;
|
|
|
- attrib_list[n++] = true;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_stereo) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " STEREO";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_STEREO;
|
|
|
- attrib_list[n++] = true;
|
|
|
- } else {
|
|
|
- attrib_list[n++] = GLX_STEREO;
|
|
|
- attrib_list[n++] = false;
|
|
|
- }
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_depth) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_DEPTH_SIZE;
|
|
|
- attrib_list[n++] = want_depth_bits;
|
|
|
- }
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_stencil) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " STENCIL(" << want_stencil_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_STENCIL_SIZE;
|
|
|
- attrib_list[n++] = want_stencil_bits;
|
|
|
- }
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_accum) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " ACCUM";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_ACCUM_RED_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
|
|
|
- attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
|
|
|
- attrib_list[n++] = want_alpha_bits;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " MULTISAMPLE(" << want_multisamples << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_SAMPLE_BUFFERS;
|
|
|
- attrib_list[n++] = 1;
|
|
|
- attrib_list[n++] = GLX_SAMPLES;
|
|
|
- attrib_list[n++] = want_multisamples;
|
|
|
- }
|
|
|
-
|
|
|
- // Terminate the list
|
|
|
- nassertr(n < max_attrib_list, None);
|
|
|
- attrib_list[n] = (int)None;
|
|
|
-
|
|
|
- int num_configs = 0;
|
|
|
- GLXFBConfig *configs =
|
|
|
- glXChooseFBConfig(_display, _screen, attrib_list, &num_configs);
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- if (configs != NULL) {
|
|
|
- glxdisplay_cat.debug(false)
|
|
|
- << ", " << num_configs << " matches found!\n";
|
|
|
- } else {
|
|
|
- glxdisplay_cat.debug(false) << ", no match.\n";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (configs == NULL || num_configs == 0) {
|
|
|
- return None;
|
|
|
- }
|
|
|
-
|
|
|
- // Pick the first matching fbconfig; this will be the "best" one
|
|
|
- // according to the GLX specifics.
|
|
|
- GLXFBConfig fbconfig = configs[0];
|
|
|
- XFree(configs);
|
|
|
-
|
|
|
- return fbconfig;
|
|
|
-}
|
|
|
-#endif // HAVE_GLXFBCONFIG
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: glxGraphicsPipe::choose visual
|
|
|
-// Access: Private
|
|
|
-// Description: Selects an appropriate X visual for the given frame
|
|
|
-// buffer properties. Returns the visual pointer if
|
|
|
-// successful, or NULL otherwise.
|
|
|
-//
|
|
|
-// If successful, this may modify properties to reflect
|
|
|
-// the actual visual chosen.
|
|
|
-//
|
|
|
-// This is an older GLX interface, replaced by the new
|
|
|
-// fbconfig interface. However, some implementations of
|
|
|
-// GLX may not support fbconfig, so we have to have this
|
|
|
-// code as a fallback.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-XVisualInfo *glxGraphicsPipe::
|
|
|
-choose_visual(FrameBufferProperties &properties) const {
|
|
|
- int frame_buffer_mode = 0;
|
|
|
-
|
|
|
- if (properties.has_frame_buffer_mode()) {
|
|
|
- frame_buffer_mode = properties.get_frame_buffer_mode();
|
|
|
- }
|
|
|
-
|
|
|
- int want_depth_bits = properties.get_depth_bits();
|
|
|
- int want_color_bits = properties.get_color_bits();
|
|
|
- int want_alpha_bits = properties.get_alpha_bits();
|
|
|
- int want_stencil_bits = properties.get_stencil_bits();
|
|
|
- int want_multisamples = properties.get_multisamples();
|
|
|
-
|
|
|
- XVisualInfo *visual =
|
|
|
- try_for_visual(frame_buffer_mode, want_depth_bits, want_color_bits,
|
|
|
- want_alpha_bits, want_stencil_bits, want_multisamples);
|
|
|
-
|
|
|
- if (visual == NULL) {
|
|
|
- glxdisplay_cat.info()
|
|
|
- << "glxGraphicsPipe::choose_visual() - visual with requested "
|
|
|
- << " capabilities not found; trying for lesser visual.\n";
|
|
|
-
|
|
|
- bool special_size_request =
|
|
|
- (want_depth_bits != 1 || want_color_bits != 1);
|
|
|
-
|
|
|
- // We try to be smart about choosing a close match for the visual.
|
|
|
- // First, we'll eliminate some of the more esoteric options one at
|
|
|
- // a time, then two at a time, and finally we'll try just the bare
|
|
|
- // minimum.
|
|
|
-
|
|
|
- if (special_size_request) {
|
|
|
- // Actually, first we'll eliminate all of the minimum sizes, to
|
|
|
- // try to open a window with all of the requested options, but
|
|
|
- // maybe not as many bits in some options as we'd like.
|
|
|
- visual = try_for_visual(frame_buffer_mode);
|
|
|
- }
|
|
|
-
|
|
|
- if (visual == NULL) {
|
|
|
- // Ok, not good enough. Now try to eliminate options, but keep
|
|
|
- // as many bits as we asked for.
|
|
|
-
|
|
|
- // This array keeps the bitmasks of options that we pull out of
|
|
|
- // the requested frame_buffer_mode, in order.
|
|
|
-
|
|
|
- pset<int> tried_masks;
|
|
|
- tried_masks.insert(frame_buffer_mode);
|
|
|
-
|
|
|
- int i;
|
|
|
- for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
|
|
|
- int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
|
|
|
- if (tried_masks.insert(new_frame_buffer_mode).second) {
|
|
|
- visual = try_for_visual(new_frame_buffer_mode, want_depth_bits,
|
|
|
- want_color_bits, want_alpha_bits,
|
|
|
- want_stencil_bits, want_multisamples);
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (special_size_request) {
|
|
|
- tried_masks.clear();
|
|
|
- tried_masks.insert(frame_buffer_mode);
|
|
|
-
|
|
|
- if (visual == NULL) {
|
|
|
- // Try once more, this time eliminating all of the size
|
|
|
- // requests.
|
|
|
- for (i = 0; visual == NULL && strip_properties[i] != 0; i++) {
|
|
|
- int new_frame_buffer_mode = frame_buffer_mode & ~strip_properties[i];
|
|
|
- if (tried_masks.insert(new_frame_buffer_mode).second) {
|
|
|
- visual = try_for_visual(new_frame_buffer_mode);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (visual == NULL) {
|
|
|
- // Here's our last-ditch desparation attempt: give us any GLX
|
|
|
- // visual at all!
|
|
|
- visual = try_for_visual(0);
|
|
|
- }
|
|
|
-
|
|
|
- if (visual == NULL) {
|
|
|
- glxdisplay_cat.error()
|
|
|
- << "Could not get any GLX visual.\n";
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- glxdisplay_cat.info()
|
|
|
- << "Got visual 0x" << hex << (int)visual->visualid << dec << ".\n";
|
|
|
-
|
|
|
- // Now update our framebuffer_mode and bit depth appropriately.
|
|
|
- int render_mode, double_buffer, stereo, red_size, green_size, blue_size,
|
|
|
- alpha_size, ared_size, agreen_size, ablue_size, aalpha_size,
|
|
|
- depth_size, stencil_size, samples;
|
|
|
-
|
|
|
- glXGetConfig(_display, visual, GLX_RGBA, &render_mode);
|
|
|
- glXGetConfig(_display, visual, GLX_DOUBLEBUFFER, &double_buffer);
|
|
|
- glXGetConfig(_display, visual, GLX_STEREO, &stereo);
|
|
|
- glXGetConfig(_display, visual, GLX_RED_SIZE, &red_size);
|
|
|
- glXGetConfig(_display, visual, GLX_GREEN_SIZE, &green_size);
|
|
|
- glXGetConfig(_display, visual, GLX_BLUE_SIZE, &blue_size);
|
|
|
- glXGetConfig(_display, visual, GLX_ALPHA_SIZE, &alpha_size);
|
|
|
- glXGetConfig(_display, visual, GLX_ACCUM_RED_SIZE, &ared_size);
|
|
|
- glXGetConfig(_display, visual, GLX_ACCUM_GREEN_SIZE, &agreen_size);
|
|
|
- glXGetConfig(_display, visual, GLX_ACCUM_BLUE_SIZE, &ablue_size);
|
|
|
- glXGetConfig(_display, visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size);
|
|
|
- glXGetConfig(_display, visual, GLX_DEPTH_SIZE, &depth_size);
|
|
|
- glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &stencil_size);
|
|
|
- glXGetConfig(_display, visual, GLX_STENCIL_SIZE, &samples);
|
|
|
-
|
|
|
- frame_buffer_mode = 0;
|
|
|
- if (double_buffer) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_double_buffer;
|
|
|
- }
|
|
|
- if (stereo) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_stereo;
|
|
|
- }
|
|
|
- if (!render_mode) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_index;
|
|
|
- }
|
|
|
- if (stencil_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_stencil;
|
|
|
- }
|
|
|
- if (depth_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_depth;
|
|
|
- }
|
|
|
- if (alpha_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_alpha;
|
|
|
- }
|
|
|
- if (ared_size + agreen_size + ablue_size != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_accum;
|
|
|
- }
|
|
|
- if (samples != 0) {
|
|
|
- frame_buffer_mode |= FrameBufferProperties::FM_multisample;
|
|
|
- }
|
|
|
-
|
|
|
- properties.set_frame_buffer_mode(frame_buffer_mode);
|
|
|
- properties.set_color_bits(red_size + green_size + blue_size);
|
|
|
- properties.set_alpha_bits(alpha_size);
|
|
|
- properties.set_depth_bits(depth_size);
|
|
|
- properties.set_stencil_bits(stencil_size);
|
|
|
- properties.set_multisamples(samples);
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug()
|
|
|
- << "GLX Visual Info (# bits of each):" << endl
|
|
|
- << " RGBA: " << red_size << " " << green_size << " " << blue_size
|
|
|
- << " " << alpha_size << endl
|
|
|
- << " Accum RGBA: " << ared_size << " " << agreen_size << " "
|
|
|
- << ablue_size << " " << aalpha_size << endl
|
|
|
- << " Depth: " << depth_size << endl
|
|
|
- << " Stencil: " << stencil_size << endl
|
|
|
- << " Samples: " << samples << endl
|
|
|
- << " DoubleBuffer? " << double_buffer << endl
|
|
|
- << " Stereo? " << stereo << endl;
|
|
|
- }
|
|
|
-
|
|
|
- return visual;
|
|
|
-}
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: glxGraphicsPipe::try_for_visual
|
|
|
-// Access: Private
|
|
|
-// Description: Attempt to get the requested visual, if it is
|
|
|
-// available. It's just a wrapper around
|
|
|
-// glXChooseVisual(). It returns the visual information
|
|
|
-// if possible, or NULL if it is not.
|
|
|
-//
|
|
|
-// This is an older GLX interface, replaced by the new
|
|
|
-// fbconfig interface. However, some implementations of
|
|
|
-// GLX may not support fbconfig, so we have to have this
|
|
|
-// code as a fallback.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-XVisualInfo *glxGraphicsPipe::
|
|
|
-try_for_visual(int framebuffer_mode,
|
|
|
- int want_depth_bits, int want_color_bits,
|
|
|
- int want_alpha_bits, int want_stencil_bits,
|
|
|
- int want_multisamples) const {
|
|
|
- static const int max_attrib_list = 32;
|
|
|
- int attrib_list[max_attrib_list];
|
|
|
- int n=0;
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug()
|
|
|
- << "Trying for visual with: RGB(" << want_color_bits << ")";
|
|
|
- }
|
|
|
-
|
|
|
- int want_color_component_bits = max(want_color_bits / 3, 1);
|
|
|
-
|
|
|
- attrib_list[n++] = GLX_RGBA;
|
|
|
- attrib_list[n++] = GLX_RED_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_GREEN_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_BLUE_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
-
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " ALPHA(" << want_alpha_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_ALPHA_SIZE;
|
|
|
- attrib_list[n++] = want_alpha_bits;
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_double_buffer) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " DOUBLEBUFFER";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_DOUBLEBUFFER;
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_stereo) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " STEREO";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_STEREO;
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_depth) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " DEPTH(" << want_depth_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_DEPTH_SIZE;
|
|
|
- attrib_list[n++] = want_depth_bits;
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_stencil) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " STENCIL(" << want_stencil_bits << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_STENCIL_SIZE;
|
|
|
- attrib_list[n++] = want_stencil_bits;
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_accum) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " ACCUM";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_ACCUM_RED_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_ACCUM_GREEN_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- attrib_list[n++] = GLX_ACCUM_BLUE_SIZE;
|
|
|
- attrib_list[n++] = want_color_component_bits;
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_alpha) {
|
|
|
- attrib_list[n++] = GLX_ACCUM_ALPHA_SIZE;
|
|
|
- attrib_list[n++] = want_alpha_bits;
|
|
|
- }
|
|
|
- }
|
|
|
- if (framebuffer_mode & FrameBufferProperties::FM_multisample) {
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- glxdisplay_cat.debug(false) << " MULTISAMPLE(" << want_multisamples << ")";
|
|
|
- }
|
|
|
- attrib_list[n++] = GLX_SAMPLES;
|
|
|
- attrib_list[n++] = want_multisamples;
|
|
|
- }
|
|
|
-
|
|
|
- // Terminate the list
|
|
|
- nassertr(n < max_attrib_list, NULL);
|
|
|
- attrib_list[n] = (int)None;
|
|
|
-
|
|
|
- XVisualInfo *vinfo = glXChooseVisual(_display, _screen, attrib_list);
|
|
|
-
|
|
|
- if (glxdisplay_cat.is_debug()) {
|
|
|
- if (vinfo != NULL) {
|
|
|
- glxdisplay_cat.debug(false) << ", match found!\n";
|
|
|
- } else {
|
|
|
- glxdisplay_cat.debug(false) << ", no match.\n";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return vinfo;
|
|
|
-}
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: glxGraphicsPipe::make_hidden_cursor
|
|
|
// Access: Private
|