GlxContext::GlxContext(GlxContext* shared) : m_display (NULL), m_window (0), m_context (NULL), m_pbuffer (0), m_ownsWindow(false) { // Save the creation settings m_settings = ContextSettings(); // Make sure that extensions are initialized if this is not the shared context // The shared context is the context used to initialize the extensions if (shared && shared->m_display) ensureExtensionsInit(shared->m_display, DefaultScreen(shared->m_display)); // Create the rendering surface (window or pbuffer if supported) createSurface(shared, 1, 1, VideoMode::getDesktopMode().bitsPerPixel); // Create the context createContext(shared); }
GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : m_display (NULL), m_window (0), m_context (NULL), m_pbuffer (0), m_ownsWindow(false) { // Save the creation settings m_settings = settings; // Make sure that extensions are initialized if this is not the shared context // The shared context is the context used to initialize the extensions if (shared && shared->m_display) ensureExtensionsInit(shared->m_display, DefaultScreen(shared->m_display)); // Create the rendering surface from the owner window createSurface(static_cast< ::Window>(owner->getSystemHandle())); // Create the context createContext(shared); }
void GlxContext::setVerticalSyncEnabled(bool enabled) { // Make sure that extensions are initialized ensureExtensionsInit(m_display, DefaultScreen(m_display)); int result = 0; // Prioritize the EXT variant and fall back to MESA or SGI if needed // We use the direct pointer to the MESA entry point instead of the alias // because glx.h declares the entry point as an external function // which would require us to link in an additional library if (sfglx_ext_EXT_swap_control == sfglx_LOAD_SUCCEEDED) { glXSwapIntervalEXT(m_display, m_pbuffer ? m_pbuffer : m_window, enabled ? 1 : 0); } else if (sfglx_ext_MESA_swap_control == sfglx_LOAD_SUCCEEDED) { result = sf_ptrc_glXSwapIntervalMESA(enabled ? 1 : 0); } else if (sfglx_ext_SGI_swap_control == sfglx_LOAD_SUCCEEDED) { result = glXSwapIntervalSGI(enabled ? 1 : 0); } else { static bool warned = false; if (!warned) { err() << "Setting vertical sync not supported" << std::endl; warned = true; } } if (result != 0) err() << "Setting vertical sync failed" << std::endl; }
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { // Save the creation settings m_settings = settings; // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { err() << "Failed to get the window attributes" << std::endl; return; } // Get its visuals XVisualInfo tpl; tpl.screen = DefaultScreen(m_display); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // There are no GLX versions prior to 1.0 int major = 0; int minor = 0; if (!glXQueryVersion(m_display, &major, &minor)) err() << "Failed to query GLX version, limited to legacy context creation" << std::endl; // Make sure that extensions are initialized if this is not the shared context // The shared context is the context used to initialize the extensions if (shared) ensureExtensionsInit(m_display, DefaultScreen(m_display)); // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3)); // Check if we need to use glXCreateContextAttribsARB bool needCreateContextArb = false; if (m_settings.attributeFlags) needCreateContextArb = true; else if (m_settings.majorVersion >= 3) needCreateContextArb = true; // Create the OpenGL context -- first try using glXCreateContextAttribsARB if we need to if (hasCreateContextArb && needCreateContextArb) { // Get a GLXFBConfig that matches the the window's visual, for glXCreateContextAttribsARB GLXFBConfig* config = NULL; // We don't supply attributes to match against, since // the visual we are matching against was already // deemed suitable in selectBestVisual() int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); for (int i = 0; configs && (i < nbConfigs); ++i) { XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); if (!visual) continue; if (visual->visualid == visualInfo->visualid) { config = &configs[i]; break; } } if (!config) err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl; while (config && !m_context && m_settings.majorVersion) { // Check if setting the profile is supported if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) { int profile = (m_settings.attributeFlags & ContextSettings::Core) ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; int debug = (m_settings.attributeFlags & ContextSettings::Debug) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; // Create the context int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), GLX_CONTEXT_PROFILE_MASK_ARB, profile, GLX_CONTEXT_FLAGS_ARB, debug, 0, 0 }; // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes); } else { if ((m_settings.attributeFlags & ContextSettings::Core) || (m_settings.attributeFlags & ContextSettings::Debug)) err() << "Selecting a profile during context creation is not supported," << "disabling comptibility and debug" << std::endl; m_settings.attributeFlags = ContextSettings::Default; // Create the context int attributes[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), 0, 0 }; // RAII GLX error handler (we simply ignore errors here) // On an error, glXCreateContextAttribsARB will return 0 anyway GlxErrorHandler handler(m_display); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes); } if (!m_context) { // If we couldn't create the context, first try disabling flags, // then lower the version number and try again -- stop at 0.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (m_settings.attributeFlags != ContextSettings::Default) { m_settings.attributeFlags = ContextSettings::Default; } else if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; m_settings.attributeFlags = settings.attributeFlags; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; m_settings.attributeFlags = settings.attributeFlags; } } } if (configs) XFree(configs); } // If glXCreateContextAttribsARB failed, use glXCreateContext if (!m_context) { // set the context version to 2.1 (arbitrary) and disable flags m_settings.majorVersion = 2; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; #if defined(GLX_DEBUGGING) GlxErrorHandler handler(m_display); #endif // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); #if defined(GLX_DEBUGGING) if (glxErrorOccurred) err() << "GLX error in GlxContext::createContext()" << std::endl; #endif } if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; } else { // Update the creation settings from the chosen format int depth, stencil, multiSampling, samples; glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED) { glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); } else { multiSampling = 0; samples = 0; } m_settings.depthBits = static_cast<unsigned int>(depth); m_settings.stencilBits = static_cast<unsigned int>(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; } // Free the visual info XFree(visualInfo); }