//////////////////////////////////////////////////////////// /// Construct the context from graphics settings //////////////////////////////////////////////////////////// void WindowImplWin32::CreateContext(const VideoMode& Mode, WindowSettings& Params) { // Get the device context attached to the window myDeviceContext = GetDC(myHandle); if (myDeviceContext == NULL) { std::cerr << "Failed to get device context of window -- cannot create OpenGL context" << std::endl; return; } // Let's find a suitable pixel format -- first try with antialiasing int BestFormat = 0; if (Params.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, (Params.AntialiasingLevel ? GL_TRUE : GL_FALSE), WGL_SAMPLES_ARB, Params.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(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0; if (!IsValid || (NbFormats == 0)) { if (Params.AntialiasingLevel > 2) { // No format matching our needs : reduce the multisampling level std::cerr << "Failed to find a pixel format supporting " << Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl; Params.AntialiasingLevel = IntAttributes[11] = 2; IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0; } if (!IsValid || (NbFormats == 0)) { // Cannot find any pixel format supporting multisampling ; disabling antialiasing std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl; Params.AntialiasingLevel = 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 Attribs; Attribs.nSize = sizeof(PIXELFORMATDESCRIPTOR); Attribs.nVersion = 1; DescribePixelFormat(myDeviceContext, Formats[i], sizeof(PIXELFORMATDESCRIPTOR), &Attribs); // Evaluate the current configuration int Color = Attribs.cRedBits + Attribs.cGreenBits + Attribs.cBlueBits + Attribs.cAlphaBits; int Score = EvaluateConfig(Mode, Params, Color, Attribs.cDepthBits, Attribs.cStencilBits, Params.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 std::cerr << "Antialiasing is not supported ; it will be disabled" << std::endl; Params.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 PixelDescriptor; ZeroMemory(&PixelDescriptor, sizeof(PIXELFORMATDESCRIPTOR)); PixelDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR); PixelDescriptor.nVersion = 1; PixelDescriptor.iLayerType = PFD_MAIN_PLANE; PixelDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; PixelDescriptor.iPixelType = PFD_TYPE_RGBA; PixelDescriptor.cColorBits = static_cast<BYTE>(Mode.BitsPerPixel); PixelDescriptor.cDepthBits = static_cast<BYTE>(Params.DepthBits); PixelDescriptor.cStencilBits = static_cast<BYTE>(Params.StencilBits); PixelDescriptor.cAlphaBits = Mode.BitsPerPixel == 32 ? 8 : 0; // Get the pixel format that best matches our requirements BestFormat = ChoosePixelFormat(myDeviceContext, &PixelDescriptor); if (BestFormat == 0) { std::cerr << "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(PIXELFORMATDESCRIPTOR); ActualFormat.nVersion = 1; DescribePixelFormat(myDeviceContext, BestFormat, sizeof(PIXELFORMATDESCRIPTOR), &ActualFormat); Params.DepthBits = ActualFormat.cDepthBits; Params.StencilBits = ActualFormat.cStencilBits; // Set the chosen pixel format if (!SetPixelFormat(myDeviceContext, BestFormat, &ActualFormat)) { std::cerr << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl; return; } // Create the OpenGL context from the device context myGLContext = wglCreateContext(myDeviceContext); if (myGLContext == NULL) { std::cerr << "Failed to create an OpenGL context for this window" << std::endl; return; } // Share display lists with other contexts HGLRC CurrentContext = wglGetCurrentContext(); if (CurrentContext) wglShareLists(CurrentContext, myGLContext); // Activate the context SetActive(true); // Enable multisampling if (Params.AntialiasingLevel > 0) glEnable(GL_MULTISAMPLE_ARB); }
//////////////////////////////////////////////////////////// /// Create the OpenGL rendering context //////////////////////////////////////////////////////////// bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template, unsigned long Mask) { // Get all the visuals matching the template Template.screen = ourScreen; int NbVisuals = 0; XVisualInfo* Visuals = XGetVisualInfo(ourDisplay, Mask | VisualScreenMask, &Template, &NbVisuals); if (!Visuals || (NbVisuals == 0)) { if (Visuals) XFree(Visuals); std::cerr << "There is no valid visual for the selected screen" << std::endl; return false; } // Find the best visual int BestScore = 0xFFFF; XVisualInfo* BestVisual = NULL; while (!BestVisual) { for (int i = 0; i < NbVisuals; ++i) { // Get the current visual attributes int RGBA, DoubleBuffer, Red, Green, Blue, Alpha, Depth, Stencil, MultiSampling, Samples; glXGetConfig(ourDisplay, &Visuals[i], GLX_RGBA, &RGBA); glXGetConfig(ourDisplay, &Visuals[i], GLX_DOUBLEBUFFER, &DoubleBuffer); glXGetConfig(ourDisplay, &Visuals[i], GLX_RED_SIZE, &Red); glXGetConfig(ourDisplay, &Visuals[i], GLX_GREEN_SIZE, &Green); glXGetConfig(ourDisplay, &Visuals[i], GLX_BLUE_SIZE, &Blue); glXGetConfig(ourDisplay, &Visuals[i], GLX_ALPHA_SIZE, &Alpha); glXGetConfig(ourDisplay, &Visuals[i], GLX_DEPTH_SIZE, &Depth); glXGetConfig(ourDisplay, &Visuals[i], GLX_STENCIL_SIZE, &Stencil); glXGetConfig(ourDisplay, &Visuals[i], GLX_SAMPLE_BUFFERS_ARB, &MultiSampling); glXGetConfig(ourDisplay, &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 = EvaluateConfig(Mode, Params, Color, Depth, Stencil, MultiSampling ? Samples : 0); // Keep it if it's better than the current best if (Score < BestScore) { BestScore = Score; BestVisual = &Visuals[i]; } } // If no visual has been found, try a lower level of antialiasing if (!BestVisual) { if (Params.AntialiasingLevel > 2) { std::cerr << "Failed to find a pixel format supporting " << Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl; Params.AntialiasingLevel = 2; } else if (Params.AntialiasingLevel > 0) { std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl; Params.AntialiasingLevel = 0; } else { std::cerr << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl; return false; } } } // Create the OpenGL context myGLContext = glXCreateContext(ourDisplay, BestVisual, glXGetCurrentContext(), true); if (myGLContext == NULL) { std::cerr << "Failed to create an OpenGL context for this window" << std::endl; return false; } // Update the creation settings from the chosen format int Depth, Stencil; glXGetConfig(ourDisplay, BestVisual, GLX_DEPTH_SIZE, &Depth); glXGetConfig(ourDisplay, BestVisual, GLX_STENCIL_SIZE, &Stencil); Params.DepthBits = static_cast<unsigned int>(Depth); Params.StencilBits = static_cast<unsigned int>(Stencil); // Assign the chosen visual, and free the temporary visuals array ChosenVisual = *BestVisual; XFree(Visuals); // Activate the context SetActive(true); // Enable multisampling if needed if (Params.AntialiasingLevel > 0) glEnable(GL_MULTISAMPLE_ARB); return true; }