XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) { // Retrieve all the visuals int count; XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); if (visuals) { // Evaluate all the returned visuals, and pick the best one int bestScore = 0xFFFF; XVisualInfo bestVisual; for (int i = 0; i < count; ++i) { // Check mandatory attributes int doubleBuffer; glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); if (!doubleBuffer) continue; // Extract the components of the current visual int red, green, blue, alpha, depth, stencil, multiSampling, samples; glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red); glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green); glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue); glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha); glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth); glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil); glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples); // Evaluate the visual int color = red + green + blue + alpha; int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0); // If it's better than the current best, make it the new best if (score < bestScore) { bestScore = score; bestVisual = visuals[i]; } } // Free the array of visuals XFree(visuals); return bestVisual; } else { // Should never happen... err() << "No GLX visual found. You should check your graphics driver" << std::endl; return XVisualInfo(); } }
void GLContextWin32::createContext(GLContextWin32 *shared, uint32 bpp, const ContextSettings &settings) { mSettings = settings; int bestFormat = 0; if (mSettings.aaLevel > 0) { PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpretCast(PFNWGLCHOOSEPIXELFORMATARBPROC, wglGetProcAddress("wglChoosePixelFormatARB")); if (wglChoosePixelFormatARB) { int intAttributes[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_SAMPLE_BUFFERS_ARB, (mSettings.aaLevel ? GL_TRUE : GL_FALSE), WGL_SAMPLES_ARB, staticCasti(mSettings.aaLevel), 0, 0 }; int formats[128]; UINT nbFormats; float floatAttributes[] = {0, 0}; bool isValid = wglChoosePixelFormatARB(mDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; while ((!isValid || (nbFormats == 0)) && mSettings.aaLevel > 0) { --mSettings.aaLevel; intAttributes[11] = mSettings.aaLevel; isValid = wglChoosePixelFormatARB(mDeviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; } if (isValid && nbFormats != 0) { int bestScore = 0xFFFF; for (UINT i = 0; i < nbFormats; ++i) { PIXELFORMATDESCRIPTOR attributes; attributes.nSize = sizeof(attributes); attributes.nVersion = 1; DescribePixelFormat(mDeviceContext, formats[i], sizeof(attributes), &attributes); int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; int score = evaluateFormat(bpp, mSettings, color, attributes.cDepthBits, attributes.cStencilBits, mSettings.aaLevel); if (score < bestScore) { bestScore = score; bestFormat = formats[i]; } } } } else { std::cerr << "Could not set aa.\n"; mSettings.aaLevel = 0; } } if (bestFormat == 0) { PIXELFORMATDESCRIPTOR descriptor; ZeroMemory(&descriptor, sizeof(descriptor)); descriptor.nSize = sizeof(descriptor); descriptor.nVersion = 1; descriptor.iLayerType = PFD_MAIN_PLANE; descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; descriptor.iPixelType = PFD_TYPE_RGBA; descriptor.cColorBits = staticCast(BYTE, bpp); descriptor.cDepthBits = staticCast(BYTE, mSettings.depthBits); descriptor.cStencilBits = staticCast(BYTE, mSettings.stencilBits); descriptor.cAlphaBits = bpp == 32 ? 8 : 0; bestFormat = ChoosePixelFormat(mDeviceContext, &descriptor); if (bestFormat == 0) { std::cerr << "Failed to find a suitable pixel format for device context, cannot create OpenGL context.\n"; return; } } PIXELFORMATDESCRIPTOR actualFormat; actualFormat.nSize = sizeof(actualFormat); actualFormat.nVersion = 1; DescribePixelFormat(mDeviceContext, bestFormat, sizeof(actualFormat), &actualFormat); mSettings.depthBits = actualFormat.cDepthBits; mSettings.stencilBits = actualFormat.cStencilBits; if (!SetPixelFormat(mDeviceContext, bestFormat, &actualFormat)) { std::cerr << "Failed to set pixel format for the devicecontext, cannot create opengl context.\n"; return; } HGLRC sharedContext = shared ? shared->mContext : null; while (!mContext && (mSettings.majorVersion >= 3)) { PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpretCast(PFNWGLCREATECONTEXTATTRIBSARBPROC, wglGetProcAddress("wglCreateContextAttribsARB")); if (wglCreateContextAttribsARB) { int attributes[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, staticCasti(mSettings.majorVersion), WGL_CONTEXT_MINOR_VERSION_ARB, staticCasti(mSettings.minorVersion), WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0, 0 }; mContext = wglCreateContextAttribsARB(mDeviceContext, sharedContext, attributes); } else { std::cerr << "Could not find \"wglCreateContextAttribsARB\".\n"; } if (!mContext) { if (mSettings.minorVersion > 0) { --mSettings.minorVersion; } else { --mSettings.majorVersion; mSettings.minorVersion = 9; } } } //no opengl >= 3 if (!mContext) { mSettings.majorVersion = 2; mSettings.minorVersion = 0; mContext = wglCreateContext(mDeviceContext); if (!mContext) { std::cerr << "Failed to create an opengl context for this window.\n"; return; } if (sharedContext) { static Mutex mutex; Lock lock(mutex); if (!wglShareLists(sharedContext, mContext)) { std::cerr << "Failed to share the opengl context.\n"; } } } }
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { // Save the creation settings m_settings = settings; // Get 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; } // Setup the visual infos to match XVisualInfo tpl; tpl.depth = windowAttributes.depth; tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); tpl.screen = DefaultScreen(m_display); // Get all the visuals matching the template int nbVisuals = 0; XVisualInfo* visuals = XGetVisualInfo(m_display, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); if (!visuals || (nbVisuals == 0)) { if (visuals) XFree(visuals); err() << "There is no valid visual for the selected screen" << std::endl; return; } // Find the best visual int bestScore = 0xFFFF; XVisualInfo* bestVisual = NULL; for (int i = 0; i < nbVisuals; ++i) { // Get the current visual attributes int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples; glXGetConfig(m_display, &visuals[i], GLX_RGBA, &RGBA); glXGetConfig(m_display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); glXGetConfig(m_display, &visuals[i], GLX_RED_SIZE, &red); glXGetConfig(m_display, &visuals[i], GLX_GREEN_SIZE, &green); glXGetConfig(m_display, &visuals[i], GLX_BLUE_SIZE, &blue); glXGetConfig(m_display, &visuals[i], GLX_ALPHA_SIZE, &alpha); glXGetConfig(m_display, &visuals[i], GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, &visuals[i], GLX_STENCIL_SIZE, &stencil); glXGetConfig(m_display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(m_display, &visuals[i], GLX_SAMPLES_ARB, &samples); // First check the mandatory parameters if ((RGBA == 0) || (doubleBuffer == 0)) continue; // Evaluate the current configuration int color = red + green + blue + alpha; int score = evaluateFormat(bitsPerPixel, m_settings, color, depth, stencil, multiSampling ? samples : 0); // Keep it if it's better than the current best if (score < bestScore) { bestScore = score; bestVisual = &visuals[i]; } } // Make sure that we have found a visual if (!bestVisual) { err() << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl; return; } // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) while (!m_context && (m_settings.majorVersion >= 3)) { const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name)); if (glXCreateContextAttribsARB) { int nbConfigs = 0; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); if (configs && nbConfigs) { // 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, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0, 0 }; m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); } if (configs) XFree(configs); } // If we couldn't create the context, lower the version number and try again -- stop at 3.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (!m_context) { if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; } } } // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context if (!m_context) { // set the context version to 2.0 (arbitrary) m_settings.majorVersion = 2; m_settings.minorVersion = 0; m_context = glXCreateContext(m_display, bestVisual, toShare, true); if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; return; } } // Update the creation settings from the chosen format int depth, stencil, multiSampling, samples; glXGetConfig(m_display, bestVisual, GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, bestVisual, GLX_STENCIL_SIZE, &stencil); glXGetConfig(m_display, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); glXGetConfig(m_display, bestVisual, GLX_SAMPLES_ARB, &samples); m_settings.depthBits = static_cast<unsigned int>(depth); m_settings.stencilBits = static_cast<unsigned int>(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; // Change the target window's colormap so that it matches the context's one ::Window root = RootWindow(m_display, DefaultScreen(m_display)); Colormap colorMap = XCreateColormap(m_display, root, bestVisual->visual, AllocNone); XSetWindowColormap(m_display, m_window, colorMap); // Free the temporary visuals array XFree(visuals); }
void WglContext::createContext(WglContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { // Save the creation settings m_settings = settings; // Let's find a suitable pixel format -- first try with antialiasing int bestFormat = 0; if (m_settings.antialiasingLevel > 0) { // Get the wglChoosePixelFormatARB function (it is an extension) PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB")); if (wglChoosePixelFormatARB) { // Define the basic attributes we want for our window int intAttributes[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_SAMPLE_BUFFERS_ARB, (m_settings.antialiasingLevel ? GL_TRUE : GL_FALSE), WGL_SAMPLES_ARB, static_cast<int>(m_settings.antialiasingLevel), 0, 0 }; // Let's check how many formats are supporting our requirements int formats[128]; UINT nbFormats; float floatAttributes[] = {0, 0}; bool isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; while ((!isValid || (nbFormats == 0)) && m_settings.antialiasingLevel > 0) { // Decrease the antialiasing level until we find a valid one m_settings.antialiasingLevel--; intAttributes[11] = m_settings.antialiasingLevel; isValid = wglChoosePixelFormatARB(m_deviceContext, intAttributes, floatAttributes, sizeof(formats) / sizeof(*formats), formats, &nbFormats) != 0; } // Get the best format among the returned ones if (isValid && (nbFormats > 0)) { int bestScore = 0xFFFF; for (UINT i = 0; i < nbFormats; ++i) { // Get the current format's attributes PIXELFORMATDESCRIPTOR attributes; attributes.nSize = sizeof(attributes); attributes.nVersion = 1; DescribePixelFormat(m_deviceContext, formats[i], sizeof(attributes), &attributes); // Evaluate the current configuration int color = attributes.cRedBits + attributes.cGreenBits + attributes.cBlueBits + attributes.cAlphaBits; int score = evaluateFormat(bitsPerPixel, m_settings, color, attributes.cDepthBits, attributes.cStencilBits, m_settings.antialiasingLevel); // Keep it if it's better than the current best if (score < bestScore) { bestScore = score; bestFormat = formats[i]; } } } } else { // wglChoosePixelFormatARB not supported ; disabling antialiasing err() << "Antialiasing is not supported ; it will be disabled" << std::endl; m_settings.antialiasingLevel = 0; } } // Find a pixel format with no antialiasing, if not needed or not supported if (bestFormat == 0) { // Setup a pixel format descriptor from the rendering settings PIXELFORMATDESCRIPTOR descriptor; ZeroMemory(&descriptor, sizeof(descriptor)); descriptor.nSize = sizeof(descriptor); descriptor.nVersion = 1; descriptor.iLayerType = PFD_MAIN_PLANE; descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; descriptor.iPixelType = PFD_TYPE_RGBA; descriptor.cColorBits = static_cast<BYTE>(bitsPerPixel); descriptor.cDepthBits = static_cast<BYTE>(m_settings.depthBits); descriptor.cStencilBits = static_cast<BYTE>(m_settings.stencilBits); descriptor.cAlphaBits = bitsPerPixel == 32 ? 8 : 0; // Get the pixel format that best matches our requirements bestFormat = ChoosePixelFormat(m_deviceContext, &descriptor); if (bestFormat == 0) { err() << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl; return; } } // Extract the depth and stencil bits from the chosen format PIXELFORMATDESCRIPTOR actualFormat; actualFormat.nSize = sizeof(actualFormat); actualFormat.nVersion = 1; DescribePixelFormat(m_deviceContext, bestFormat, sizeof(actualFormat), &actualFormat); m_settings.depthBits = actualFormat.cDepthBits; m_settings.stencilBits = actualFormat.cStencilBits; // Set the chosen pixel format if (!SetPixelFormat(m_deviceContext, bestFormat, &actualFormat)) { err() << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; return; } // Get the context to share display lists with HGLRC sharedContext = shared ? shared->m_context : NULL; // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) while (!m_context && (m_settings.majorVersion >= 3)) { PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB")); if (wglCreateContextAttribsARB) { int attributes[] = { WGL_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), WGL_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0, 0 }; m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, attributes); } // If we couldn't create the context, lower the version number and try again -- stop at 3.0 // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care if (!m_context) { if (m_settings.minorVersion > 0) { // If the minor version is not 0, we decrease it and try again m_settings.minorVersion--; } else { // If the minor version is 0, we decrease the major version m_settings.majorVersion--; m_settings.minorVersion = 9; } } } // If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context if (!m_context) { // set the context version to 2.0 (arbitrary) m_settings.majorVersion = 2; m_settings.minorVersion = 0; m_context = wglCreateContext(m_deviceContext); if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; return; } // Share this context with others if (sharedContext) { // wglShareLists doesn't seem to be thread-safe static Mutex mutex; Lock lock(mutex); if (!wglShareLists(sharedContext, m_context)) err() << "Failed to share the OpenGL context" << std::endl; } } }