Esempio n. 1
0
////////////////////////////////////////////////////////////
/// 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);
}
Esempio n. 2
0
////////////////////////////////////////////////////////////
/// 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;
}