示例#1
0
EGLConfig QEglConfigChooser::chooseConfig()
{
    QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(m_format);
    configureAttributes.append(EGL_SURFACE_TYPE);
    configureAttributes.append(surfaceType());

    configureAttributes.append(EGL_RENDERABLE_TYPE);
    bool needsES2Plus = false;
    switch (m_format.renderableType()) {
    case QSurfaceFormat::OpenVG:
        configureAttributes.append(EGL_OPENVG_BIT);
        break;
#ifdef EGL_VERSION_1_4
    case QSurfaceFormat::DefaultRenderableType:
#ifndef QT_NO_OPENGL
        if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
            configureAttributes.append(EGL_OPENGL_BIT);
        else
#endif // QT_NO_OPENGL
            needsES2Plus = true;
        break;
    case QSurfaceFormat::OpenGL:
         configureAttributes.append(EGL_OPENGL_BIT);
         break;
#endif
    case QSurfaceFormat::OpenGLES:
        if (m_format.majorVersion() == 1) {
            configureAttributes.append(EGL_OPENGL_ES_BIT);
            break;
        }
        // fall through
    default:
        needsES2Plus = true;
        break;
    }
    if (needsES2Plus) {
        if (m_format.majorVersion() >= 3 && q_hasEglExtension(display(), "EGL_KHR_create_context"))
            configureAttributes.append(EGL_OPENGL_ES3_BIT_KHR);
        else
            configureAttributes.append(EGL_OPENGL_ES2_BIT);
    }
    configureAttributes.append(EGL_NONE);

    EGLConfig cfg = 0;
    do {
        // Get the number of matching configurations for this set of properties.
        EGLint matching = 0;
        if (!eglChooseConfig(display(), configureAttributes.constData(), 0, 0, &matching) || !matching)
            continue;

        // Fetch all of the matching configurations and find the
        // first that matches the pixel format we wanted.
        int i = configureAttributes.indexOf(EGL_RED_SIZE);
        m_confAttrRed = configureAttributes.at(i+1);
        i = configureAttributes.indexOf(EGL_GREEN_SIZE);
        m_confAttrGreen = configureAttributes.at(i+1);
        i = configureAttributes.indexOf(EGL_BLUE_SIZE);
        m_confAttrBlue = configureAttributes.at(i+1);
        i = configureAttributes.indexOf(EGL_ALPHA_SIZE);
        m_confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);

        QVector<EGLConfig> configs(matching);
        eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching);
        if (!cfg && matching > 0)
            cfg = configs.first();

        // Filter the list. Due to the EGL sorting rules configs with higher depth are
        // placed first when the minimum color channel sizes have been specified (i.e. the
        // QSurfaceFormat contains color sizes > 0). To prevent returning a 888 config
        // when the QSurfaceFormat explicitly asked for 565, go through the returned
        // configs and look for one that exactly matches the requested sizes. When no
        // sizes have been given, take the first, which will be a config with the smaller
        // (e.g. 16-bit) depth.
        for (int i = 0; i < configs.size(); ++i) {
            if (filterConfig(configs[i]))
                return configs.at(i);
        }
    } while (q_reduceConfigAttributes(&configureAttributes));

    if (!cfg)
        qWarning("Cant find EGLConfig, returning null config");
    return cfg;
}
示例#2
0
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
{
    m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
    // m_format now has the renderableType() resolved (it cannot be Default anymore)
    // but does not yet contain version, profile, options.
    m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;

    QVector<EGLint> contextAttrs;
    contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
    contextAttrs.append(format.majorVersion());
    const bool hasKHRCreateContext = q_hasEglExtension(m_eglDisplay, "EGL_KHR_create_context");
    if (hasKHRCreateContext) {
        contextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR);
        contextAttrs.append(format.minorVersion());
        int flags = 0;
        // The debug bit is supported both for OpenGL and OpenGL ES.
        if (format.testOption(QSurfaceFormat::DebugContext))
            flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
        // The fwdcompat bit is only for OpenGL 3.0+.
        if (m_format.renderableType() == QSurfaceFormat::OpenGL
            && format.majorVersion() >= 3
            && !format.testOption(QSurfaceFormat::DeprecatedFunctions))
            flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
        if (flags) {
            contextAttrs.append(EGL_CONTEXT_FLAGS_KHR);
            contextAttrs.append(flags);
        }
        // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2.
        if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
            contextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
            contextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile
                                ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
                                : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
        }
    }
    contextAttrs.append(EGL_NONE);

    switch (m_format.renderableType()) {
    case QSurfaceFormat::OpenVG:
        m_api = EGL_OPENVG_API;
        break;
#ifdef EGL_VERSION_1_4
    case QSurfaceFormat::OpenGL:
        m_api = EGL_OPENGL_API;
        break;
#endif // EGL_VERSION_1_4
    default:
        m_api = EGL_OPENGL_ES_API;
        break;
    }

    eglBindAPI(m_api);
    m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
    if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
        m_shareContext = 0;
        m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData());
    }

    if (m_eglContext == EGL_NO_CONTEXT) {
        qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError());
        return;
    }

    static const bool printConfig = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEBUG");
    if (printConfig) {
        qDebug() << "Created context for format" << format << "with config:";
        q_printEglConfig(m_eglDisplay, m_eglConfig);
    }

    // Cannot just call updateFormatFromGL() since it relies on virtuals. Defer it to initialize().
}
示例#3
0
void QEGLPlatformContext::updateFormatFromGL()
{
#ifndef QT_NO_OPENGL
    // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming
    // inconsistent after QOpenGLContext::create().
    EGLDisplay prevDisplay = eglGetCurrentDisplay();
    if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
        prevDisplay = m_eglDisplay;
    EGLContext prevContext = eglGetCurrentContext();
    EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
    EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ);

    // Rely on the surfaceless extension, if available. This is beneficial since we can
    // avoid creating an extra pbuffer surface which is apparently troublesome with some
    // drivers (Mesa) when certain attributes are present (multisampling).
    EGLSurface tempSurface = EGL_NO_SURFACE;
    if (!q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
        tempSurface = createTemporaryOffscreenSurface();

    if (eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext)) {
        if (m_format.renderableType() == QSurfaceFormat::OpenGL
            || m_format.renderableType() == QSurfaceFormat::OpenGLES) {
            const GLubyte *s = glGetString(GL_VERSION);
            if (s) {
                QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
                int major, minor;
                if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
#ifdef Q_OS_ANDROID
                    // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
                    static int apiLevel = QtAndroidPrivate::androidSdkVersion();
                    if (apiLevel <= 17 && major >= 3) {
                        major = 2;
                        minor = 0;
                    }
#endif
                    m_format.setMajorVersion(major);
                    m_format.setMinorVersion(minor);
                }
            }
            m_format.setProfile(QSurfaceFormat::NoProfile);
            m_format.setOptions(QSurfaceFormat::FormatOptions());
            if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
                // Check profile and options.
                if (m_format.majorVersion() < 3) {
                    m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
                } else {
                    GLint value = 0;
                    glGetIntegerv(GL_CONTEXT_FLAGS, &value);
                    if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
                        m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
                    if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
                        m_format.setOption(QSurfaceFormat::DebugContext);
                    if (m_format.version() >= qMakePair(3, 2)) {
                        value = 0;
                        glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
                        if (value & GL_CONTEXT_CORE_PROFILE_BIT)
                            m_format.setProfile(QSurfaceFormat::CoreProfile);
                        else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
                            m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
                    }
                }
            }
        }
        eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
    } else {
        qWarning("QEGLPlatformContext: Failed to make temporary surface current, format not updated");
    }
    if (tempSurface != EGL_NO_SURFACE)
        destroyTemporaryOffscreenSurface(tempSurface);
#endif // QT_NO_OPENGL
}
示例#4
0
VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
{
    VisualID    visualId = 0;
    EGLint      eglValue = 0;

    EGLint configRedSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize);

    EGLint configGreenSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize);

    EGLint configBlueSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize);

    EGLint configAlphaSize = 0;
    eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize);

    eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue);
    int configId = eglValue;

    // See if EGL provided a valid VisualID:
    eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue);
    visualId = (VisualID)eglValue;
    if (visualId) {
        // EGL has suggested a visual id, so get the rest of the visual info for that id:
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        visualInfoTemplate.visualid = visualId;

        XVisualInfo *chosenVisualInfo;
        int matchingCount = 0;
        chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount);
        if (chosenVisualInfo) {
            // Skip size checks if implementation supports non-matching visual
            // and config (http://bugreports.qt-project.org/browse/QTBUG-9444).
            if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) {
                XFree(chosenVisualInfo);
                return visualId;
            }

            int visualRedSize = countBits(chosenVisualInfo->red_mask);
            int visualGreenSize = countBits(chosenVisualInfo->green_mask);
            int visualBlueSize = countBits(chosenVisualInfo->blue_mask);
            int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size

            bool visualMatchesConfig = false;
            if ( visualRedSize == configRedSize &&
                 visualGreenSize == configGreenSize &&
                 visualBlueSize == configBlueSize )
            {
                // We need XRender to check the alpha channel size of the visual. If we don't have
                // the alpha size, we don't check it against the EGL config's alpha size.
                if (visualAlphaSize >= 0)
                    visualMatchesConfig = visualAlphaSize == configAlphaSize;
                else
                    visualMatchesConfig = true;
            }

            if (!visualMatchesConfig) {
                if (visualAlphaSize >= 0) {
                    qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable",
                             (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize,
                             configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize);
                } else {
                    qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable",
                             (int)visualId, visualRedSize, visualGreenSize, visualBlueSize,
                             configId, configRedSize, configGreenSize, configBlueSize);
                }
                visualId = 0;
            }
        } else {
            qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
                     (int)visualId, configId);
            visualId = 0;
        }
        XFree(chosenVisualInfo);
    }
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
    else
        qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
#endif

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        if (configAlphaSize > 0)
            qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
        else
            qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
#endif
        return visualId;
    }

    // Finally, try to
    // use XGetVisualInfo and only use the bit depths to match on:
    if (!visualId) {
        XVisualInfo visualInfoTemplate;
        memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
        XVisualInfo *matchingVisuals;
        int matchingCount = 0;

        visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
        matchingVisuals = XGetVisualInfo(display,
                                         VisualDepthMask,
                                         &visualInfoTemplate,
                                         &matchingCount);
        if (!matchingVisuals) {
            // Try again without taking the alpha channel into account:
            visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
            matchingVisuals = XGetVisualInfo(display,
                                             VisualDepthMask,
                                             &visualInfoTemplate,
                                             &matchingCount);
        }

        if (matchingVisuals) {
            visualId = matchingVisuals[0].visualid;
            XFree(matchingVisuals);
        }
    }

    if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
        qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
#endif
        return visualId;
    }

    qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
    return (VisualID)0;
}