Exemplo n.º 1
0
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();
    }
}
Exemplo n.º 2
0
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";
			}
		}
	}
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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;
        }
    }
}