// Return a list of available and usable framebuffer configs // static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result) { GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; int i, nativeCount, usableCount; const char* vendor; GLboolean trustWindowBit = GL_TRUE; vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0) { // HACK: This is a (hopefully temporary) workaround for Chromium // (VirtualBox GL) not setting the window bit on any GLXFBConfigs trustWindowBit = GL_FALSE; } if (_glfw.glx.SGIX_fbconfig) { nativeConfigs = _glfw.glx.ChooseFBConfigSGIX(_glfw.x11.display, _glfw.x11.screen, NULL, &nativeCount); } else { nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount); } if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); return GL_FALSE; } usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; for (i = 0; i < nativeCount; i++) { const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; if (!getFBConfigAttrib(n, GLX_DOUBLEBUFFER) || !getFBConfigAttrib(n, GLX_VISUAL_ID)) { // Only consider double-buffered GLXFBConfigs with associated visuals continue; } if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) { // Only consider RGBA GLXFBConfigs continue; } if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) { if (trustWindowBit) { // Only consider window GLXFBConfigs continue; } } u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE); u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE); u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE); u->alphaBits = getFBConfigAttrib(n, GLX_ALPHA_SIZE); u->depthBits = getFBConfigAttrib(n, GLX_DEPTH_SIZE); u->stencilBits = getFBConfigAttrib(n, GLX_STENCIL_SIZE); u->accumRedBits = getFBConfigAttrib(n, GLX_ACCUM_RED_SIZE); u->accumGreenBits = getFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE); u->accumBlueBits = getFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE); u->accumAlphaBits = getFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE); u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS); u->stereo = getFBConfigAttrib(n, GLX_STEREO); if (_glfw.glx.ARB_multisample) u->samples = getFBConfigAttrib(n, GLX_SAMPLES); if (_glfw.glx.ARB_framebuffer_sRGB) u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); u->glx = n; usableCount++; } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest) *result = closest->glx; XFree(nativeConfigs); free(usableConfigs); return closest ? GL_TRUE : GL_FALSE; }
static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) { GLXFBConfig* fbconfigs; _GLFWfbconfig* result; int i, count = 0; const char* vendor; GLboolean trustWindowBit = GL_TRUE; *found = 0; if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) { if (!_glfwLibrary.GLX.SGIX_fbconfig) { _glfwSetError(GLFW_API_UNAVAILABLE, "GLX: GLXFBConfig support not found"); return NULL; } } vendor = glXGetClientString(_glfwLibrary.X11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0) { // HACK: This is a (hopefully temporary) workaround for Chromium // (VirtualBox GL) not setting the window bit on any GLXFBConfigs trustWindowBit = GL_FALSE; } if (_glfwLibrary.GLX.SGIX_fbconfig) { fbconfigs = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, _glfwLibrary.X11.screen, NULL, &count); if (!count) { _glfwSetError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); return NULL; } } else { fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, _glfwLibrary.X11.screen, &count); if (!count) { _glfwSetError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); return NULL; } } result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); if (!result) { _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); return NULL; } for (i = 0; i < count; i++) { _GLFWfbconfig* f = result + *found; if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) { // Only consider double-buffered GLXFBConfigs with associated visuals continue; } if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_RENDER_TYPE) & GLX_RGBA_BIT)) { // Only consider RGBA GLXFBConfigs continue; } if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) { if (trustWindowBit) { // Only consider window GLXFBConfigs continue; } } f->redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); f->greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); f->blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); f->alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); f->depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); f->stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); f->accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); f->accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); f->accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); f->accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); f->auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); f->stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); if (_glfwLibrary.GLX.ARB_multisample) f->samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); else f->samples = 0; if (_glfwLibrary.GLX.ARB_framebuffer_sRGB) f->sRGB = getFBConfigAttrib(window, fbconfigs[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); else f->sRGB = GL_FALSE; f->platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); (*found)++; } XFree(fbconfigs); return result; }
// Return a list of available and usable framebuffer configs // static GLFWbool chooseFBConfig( const _GLFWfbconfig* desired, GLXFBConfig* result, GLFWbool findTransparent) { GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; int i, nativeCount, usableCount; const char* vendor; GLFWbool trustWindowBit = GLFW_TRUE; if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) { findTransparent = GLFW_FALSE; } // HACK: This is a (hopefully temporary) workaround for Chromium // (VirtualBox GL) not setting the window bit on any GLXFBConfigs vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0) trustWindowBit = GLFW_FALSE; nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount); if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); return GLFW_FALSE; } usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; selectionloop: for (i = 0; i < nativeCount; i++) { const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; // Only consider RGBA GLXFBConfigs if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) continue; // Only consider window GLXFBConfigs if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) { if (trustWindowBit) continue; } if( findTransparent ) { XVisualInfo *visualinfo; XRenderPictFormat *pictFormat; visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n); if (!visualinfo) continue; pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); if( !pictFormat ) { XFree( visualinfo ); continue; } if( !pictFormat->direct.alphaMask ) { XFree( visualinfo ); continue; } XFree( visualinfo ); } u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE); u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE); u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE); u->alphaBits = getFBConfigAttrib(n, GLX_ALPHA_SIZE); u->depthBits = getFBConfigAttrib(n, GLX_DEPTH_SIZE); u->stencilBits = getFBConfigAttrib(n, GLX_STENCIL_SIZE); u->accumRedBits = getFBConfigAttrib(n, GLX_ACCUM_RED_SIZE); u->accumGreenBits = getFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE); u->accumBlueBits = getFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE); u->accumAlphaBits = getFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE); u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS); if (getFBConfigAttrib(n, GLX_STEREO)) u->stereo = GLFW_TRUE; if (getFBConfigAttrib(n, GLX_DOUBLEBUFFER)) u->doublebuffer = GLFW_TRUE; if (_glfw.glx.ARB_multisample) u->samples = getFBConfigAttrib(n, GLX_SAMPLES); if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB) u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); u->glx = n; usableCount++; } // reiterate the selection loop without looking for transparency supporting // formats if no matchig FB configs for a transparent window were found. if( findTransparent && !usableCount ) { findTransparent = GLFW_FALSE; goto selectionloop; } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest) *result = closest->glx; XFree(nativeConfigs); free(usableConfigs); return closest ? GLFW_TRUE : GLFW_FALSE; }
//-------------------------------------------------------------------------------------------------// GLXGLSupport::GLXGLSupport() : mGLDisplay(0), mXDisplay(0) { // A connection that might be shared with the application for GL rendering: mGLDisplay = getGLDisplay(); // A connection that is NOT shared to enable independent event processing: mXDisplay = getXDisplay(); int dummy; if (XQueryExtension(mXDisplay, "RANDR", &dummy, &dummy, &dummy)) { XRRScreenConfiguration *screenConfig; screenConfig = XRRGetScreenInfo(mXDisplay, DefaultRootWindow(mXDisplay)); if (screenConfig) { XRRScreenSize *screenSizes; int nSizes = 0; Rotation currentRotation; int currentSizeID = XRRConfigCurrentConfiguration(screenConfig, ¤tRotation); screenSizes = XRRConfigSizes(screenConfig, &nSizes); mCurrentMode.first.first = screenSizes[currentSizeID].width; mCurrentMode.first.second = screenSizes[currentSizeID].height; mCurrentMode.second = XRRConfigCurrentRate(screenConfig); mOriginalMode = mCurrentMode; for(int sizeID = 0; sizeID < nSizes; sizeID++) { short *rates; int nRates = 0; rates = XRRConfigRates(screenConfig, sizeID, &nRates); for (int rate = 0; rate < nRates; rate++) { VideoMode mode; mode.first.first = screenSizes[sizeID].width; mode.first.second = screenSizes[sizeID].height; mode.second = rates[rate]; mVideoModes.push_back(mode); } } XRRFreeScreenConfigInfo(screenConfig); } } else { mCurrentMode.first.first = DisplayWidth(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.first.second = DisplayHeight(mXDisplay, DefaultScreen(mXDisplay)); mCurrentMode.second = 0; mOriginalMode = mCurrentMode; mVideoModes.push_back(mCurrentMode); } GLXFBConfig *fbConfigs; int config, nConfigs = 0; fbConfigs = chooseFBConfig(NULL, &nConfigs); for (config = 0; config < nConfigs; config++) { int caveat, samples; getFBConfigAttrib (fbConfigs[config], GLX_CONFIG_CAVEAT, &caveat); if (caveat != GLX_SLOW_CONFIG) { getFBConfigAttrib (fbConfigs[config], GLX_SAMPLES, &samples); mSampleLevels.push_back(StringConverter::toString(samples)); } } XFree (fbConfigs); remove_duplicates(mSampleLevels); }
// Return a list of available and usable framebuffer configs // static void chooseFBConfig(const OSGLContext_glx_data* glxInfo, const FramebufferConfig& desired, GLXFBConfig* result) { bool trustWindowBit = true; // HACK: This is a (hopefully temporary) workaround for Chromium // (VirtualBox GL) not setting the window bit on any GLXFBConfigs const char* vendor = glxInfo->_imp->GetClientString(glxInfo->_imp->x11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0) { trustWindowBit = false; } int nativeCount; GLXFBConfig* nativeConfigs = glxInfo->_imp->GetFBConfigs(glxInfo->_imp->x11.display, glxInfo->_imp->x11.screen, &nativeCount); if (!nativeCount) { throw std::runtime_error("GLX: No GLXFBConfigs returned"); } std::vector<FramebufferConfig> usableConfigs(nativeCount); int usableCount = 0; for (int i = 0; i < nativeCount; ++i) { const GLXFBConfig& n = nativeConfigs[i]; FramebufferConfig& u = usableConfigs[usableCount]; // Only consider RGBA GLXFBConfigs if ( !(getFBConfigAttrib(glxInfo, n, GLX_RENDER_TYPE) & GLX_RGBA_BIT) ) { continue; } // Only consider window GLXFBConfigs if ( !(getFBConfigAttrib(glxInfo, n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT) ) { if (trustWindowBit) { continue; } } u.redBits = getFBConfigAttrib(glxInfo, n, GLX_RED_SIZE); u.greenBits = getFBConfigAttrib(glxInfo, n, GLX_GREEN_SIZE); u.blueBits = getFBConfigAttrib(glxInfo, n, GLX_BLUE_SIZE); u.alphaBits = getFBConfigAttrib(glxInfo, n, GLX_ALPHA_SIZE); u.depthBits = getFBConfigAttrib(glxInfo, n, GLX_DEPTH_SIZE); u.stencilBits = getFBConfigAttrib(glxInfo, n, GLX_STENCIL_SIZE); u.accumRedBits = getFBConfigAttrib(glxInfo, n, GLX_ACCUM_RED_SIZE); u.accumGreenBits = getFBConfigAttrib(glxInfo, n, GLX_ACCUM_GREEN_SIZE); u.accumBlueBits = getFBConfigAttrib(glxInfo, n, GLX_ACCUM_BLUE_SIZE); u.accumAlphaBits = getFBConfigAttrib(glxInfo, n, GLX_ACCUM_ALPHA_SIZE); u.auxBuffers = getFBConfigAttrib(glxInfo, n, GLX_AUX_BUFFERS); if ( getFBConfigAttrib(glxInfo, n, GLX_STEREO) ) { u.stereo = GL_TRUE; } if ( getFBConfigAttrib(glxInfo, n, GLX_DOUBLEBUFFER) ) { u.doublebuffer = GL_TRUE; } if (glxInfo->_imp->ARB_multisample) { u.samples = getFBConfigAttrib(glxInfo, n, GLX_SAMPLES); } if (glxInfo->_imp->ARB_framebuffer_sRGB || glxInfo->_imp->EXT_framebuffer_sRGB) { u.sRGB = getFBConfigAttrib(glxInfo, n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); } u.handle = (uintptr_t) n; usableCount++; } const FramebufferConfig& closest = OSGLContext::chooseFBConfig(desired, usableConfigs, usableCount); *result = (GLXFBConfig) closest.handle; XFree(nativeConfigs); } // chooseFBConfig