static QEglContext *createContext(QPaintDevice *device)
{
    QEglContext *context;

    // Create the context object and open the display.
    context = new QEglContext();
    context->setApi(QEgl::OpenVG);
    if (!context->openDisplay(device)) {
        delete context;
        return 0;
    }

    // Set the swap interval for the display.
    QByteArray interval = qgetenv("QT_VG_SWAP_INTERVAL");
    if (!interval.isEmpty())
        eglSwapInterval(context->display(), interval.toInt());
    else
        eglSwapInterval(context->display(), 1);

    // Choose an appropriate configuration for rendering into the device.
    QEglProperties configProps;
    configProps.setPaintDeviceFormat(device);
    int redSize = configProps.value(EGL_RED_SIZE);
    if (redSize == EGL_DONT_CARE || redSize == 0)
        configProps.setPixelFormat(QImage::Format_ARGB32);  // XXX
#ifndef QVG_SCISSOR_CLIP
    // If we are using the mask to clip, then explicitly request a mask.
    configProps.setValue(EGL_ALPHA_MASK_SIZE, 1);
#endif
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
    configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT |
                         EGL_VG_ALPHA_FORMAT_PRE_BIT);
    configProps.setRenderableType(QEgl::OpenVG);
    if (!context->chooseConfig(configProps)) {
        // Try again without the "pre" bit.
        configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
        if (!context->chooseConfig(configProps)) {
            delete context;
            return 0;
        }
    }
#else
    configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
    configProps.setRenderableType(QEgl::OpenVG);
    if (!context->chooseConfig(configProps)) {
        delete context;
        return 0;
    }
#endif

    // Construct a new EGL context for the selected configuration.
    if (!context->createContext()) {
        delete context;
        return 0;
    }

    return context;
}
QT_BEGIN_NAMESPACE

void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat)
{
    int redSize     = glFormat.redBufferSize();
    int greenSize   = glFormat.greenBufferSize();
    int blueSize    = glFormat.blueBufferSize();
    int alphaSize   = glFormat.alphaBufferSize();
    int depthSize   = glFormat.depthBufferSize();
    int stencilSize = glFormat.stencilBufferSize();
    int sampleCount = glFormat.samples();

    // QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
    // type has been requested. So we must check QGLFormat's booleans too if size is -1:
    if (glFormat.alpha() && alphaSize <= 0)
        alphaSize = 1;
    if (glFormat.depth() && depthSize <= 0)
        depthSize = 1;
    if (glFormat.stencil() && stencilSize <= 0)
        stencilSize = 1;
    if (glFormat.sampleBuffers() && sampleCount <= 0)
        sampleCount = 1;

    // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
    // the best performance. The EGL config selection algorithm is a bit stange in this regard:
    // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
    // 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
    // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
    // order is special and described as "by larger _total_ number of color bits.". So EGL will
    // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
    // to say "If the requested number of bits in attrib_list for a particular component is 0,
    // then the number of bits for that component is not considered". This part of the spec also
    // seems to imply that setting the red/green/blue bits to zero means none of the components
    // are considered and EGL disregards the entire sorting rule. It then looks to the next
    // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
    // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
    // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
    // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
    // if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will
    // probably get a 32-bit config, even when there's an RGB565 config avaliable. Oh well.

    // Now normalize the values so -1 becomes 0
    redSize   = redSize   > 0 ? redSize   : 0;
    greenSize = greenSize > 0 ? greenSize : 0;
    blueSize  = blueSize  > 0 ? blueSize  : 0;
    alphaSize = alphaSize > 0 ? alphaSize : 0;
    depthSize = depthSize > 0 ? depthSize : 0;
    stencilSize = stencilSize > 0 ? stencilSize : 0;
    sampleCount = sampleCount > 0 ? sampleCount : 0;

    eglProperties.setValue(EGL_RED_SIZE,   redSize);
    eglProperties.setValue(EGL_GREEN_SIZE, greenSize);
    eglProperties.setValue(EGL_BLUE_SIZE,  blueSize);
    eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize);
    eglProperties.setValue(EGL_DEPTH_SIZE, depthSize);
    eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize);
    eglProperties.setValue(EGL_SAMPLES, sampleCount);
    eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0);
}
Example #3
0
// Retrieve all of the properties on "cfg".  If zero, return
// the context's configuration.
QEglProperties QEglContext::configProperties(EGLConfig cfg) const
{
    if (!cfg)
        cfg = config();
    QEglProperties props;
    for (int name = 0x3020; name <= 0x304F; ++name) {
        EGLint value;
        if (name != EGL_NONE && eglGetConfigAttrib(dpy, cfg, name, &value))
            props.setValue(name, value);
    }
    eglGetError();  // Clear the error state.
    return props;
}
Example #4
0
File: qegl.cpp Project: Afreeca/qt
// Create the EGLContext.
bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
{
    // We need to select the correct API before calling eglCreateContext().
#ifdef QT_OPENGL_ES
#ifdef EGL_OPENGL_ES_API
    if (apiType == QEgl::OpenGL)
        eglBindAPI(EGL_OPENGL_ES_API);
#endif
#else
#ifdef EGL_OPENGL_API
    if (apiType == QEgl::OpenGL)
        eglBindAPI(EGL_OPENGL_API);
#endif
#endif //defined(QT_OPENGL_ES)
#ifdef EGL_OPENVG_API
    if (apiType == QEgl::OpenVG)
        eglBindAPI(EGL_OPENVG_API);
#endif

    // Create a new context for the configuration.
    QEglProperties contextProps;
    if (properties)
        contextProps = *properties;
#ifdef QT_OPENGL_ES_2
    if (apiType == QEgl::OpenGL)
        contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
#endif
    sharing = false;
    if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
        shareContext = 0;
    if (shareContext) {
        ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
        if (ctx == EGL_NO_CONTEXT) {
            qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
            shareContext = 0;
        } else {
            sharing = true;
        }
    }
    if (ctx == EGL_NO_CONTEXT) {
        ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties());
        if (ctx == EGL_NO_CONTEXT) {
            qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
#ifdef Q_OS_SYMBIAN
            S60->eglSurfaceCreationError = true;
#endif
            return false;
        }
    }
    return true;
}
Example #5
0
// Create the EGLContext.
bool QEglContext::createContext(QEglContext *shareContext)
{
    // We need to select the correct API before calling eglCreateContext().
#ifdef EGL_OPENGL_ES_API
    if (apiType == OpenGL)
        eglBindAPI(EGL_OPENGL_ES_API);
#endif
#ifdef EGL_OPENVG_API
    if (apiType == OpenVG)
        eglBindAPI(EGL_OPENVG_API);
#endif

    // Create a new context for the configuration.
    QEglProperties contextProps;
#if defined(QT_OPENGL_ES_2)
    if (apiType == OpenGL)
        contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
#endif
    if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
        shareContext = 0;
    if (shareContext) {
        ctx = eglCreateContext(dpy, cfg, shareContext->ctx, contextProps.properties());
        if (ctx == EGL_NO_CONTEXT) {
            qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError());
            shareContext = 0;
        }
    }
    if (ctx == EGL_NO_CONTEXT) {
        ctx = eglCreateContext(dpy, cfg, 0, contextProps.properties());
        if (ctx == EGL_NO_CONTEXT) {
            qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << errorString(eglGetError());
            return false;
        }
    }
    share = (shareContext != 0);
    return true;
}
Example #6
0
// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't
// match the one for the passed in EGLConfig
EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *unusedProperties)
{
    Q_UNUSED(unusedProperties);

    int devType = device->devType();

    if (devType == QInternal::Pbuffer) {
        // TODO
        return EGL_NO_SURFACE;
    }

    QX11PixmapData *x11PixmapData = 0;
    if (devType == QInternal::Pixmap) {
        QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data();
        if (pmd->classId() == QPixmapData::X11Class)
            x11PixmapData = static_cast<QX11PixmapData*>(pmd);
        else {
            // TODO: Replace the pixmap's data with a new QX11PixmapData
            qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData");
            return EGL_NO_SURFACE;
        }
    } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
        qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType);
        return EGL_NO_SURFACE;
    }

    VisualID visualId = QEgl::getCompatibleVisualId(config);
    EGLint alphaSize;
    eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize);

    if (devType == QInternal::Widget) {
        QWidget *widget = static_cast<QWidget*>(device);

        VisualID currentVisualId = 0;
        if (widget->testAttribute(Qt::WA_WState_Created))
            currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual());

        if (currentVisualId != visualId) {
            // The window is either not created or has the wrong visual. Either way, we need
            // to create a window with the correct visual and call create() on the widget:

            bool visible = widget->isVisible();
            if (visible)
                widget->hide();

            XVisualInfo visualInfo;
            visualInfo.visualid = visualId;
            {
                XVisualInfo *visualInfoPtr;
                int matchingCount = 0;
                visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask,
                                               &visualInfo, &matchingCount);
                Q_ASSERT(visualInfoPtr); // visualId really should be valid!
                visualInfo = *visualInfoPtr;
                XFree(visualInfoPtr);
            }

            Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen());
            if (widget->parentWidget())
                parentWindow = widget->parentWidget()->winId();

            XSetWindowAttributes windowAttribs;
            QColormap colmap = QColormap::instance(widget->x11Info().screen());
            windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole()));
            windowAttribs.border_pixel = colmap.pixel(Qt::black);

            unsigned int valueMask = CWBackPixel|CWBorderPixel;
            if (alphaSize > 0) {
                windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow,
                                                         visualInfo.visual, AllocNone);
                valueMask |= CWColormap;
            }

            Window window = XCreateWindow(widget->x11Info().display(), parentWindow,
                                          widget->x(), widget->y(), widget->width(), widget->height(),
                                          0, visualInfo.depth, InputOutput, visualInfo.visual,
                                          valueMask, &windowAttribs);

            // This is a nasty hack to get round the fact that we can't be a friend of QWidget:
            qt_set_winid_on_widget(widget, window);

            if (visible)
                widget->show();
        }

        // At this point, the widget's window should be created and have the correct visual. Now we
        // just need to create the EGL surface for it:
        EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), 0);
        if (surf == EGL_NO_SURFACE)
            qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
        return surf;
    }

    if (x11PixmapData) {
        // X11 Pixmaps are only created with a depth, so that's all we need to check
        EGLint configDepth;
        eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth);
        if (x11PixmapData->depth() != configDepth) {
            // The bit depths are wrong which means the EGLConfig isn't compatable with
            // this pixmap. So we need to replace the pixmap's existing data with a new
            // one which is created with the correct depth:

#ifndef QT_NO_XRENDER
            if (configDepth == 32) {
                qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32",
                         x11PixmapData->depth());
                x11PixmapData->convertToARGB32(true);
            } else
#endif
            {
                qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)",
                         configDepth, x11PixmapData->depth());
            }
        }

        QEglProperties surfaceAttribs;

        // If the pixmap can't be bound to a texture, it's pretty useless
        surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
        if (alphaSize > 0)
            surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
        else
            surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);

        EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config,
                                                 (EGLNativePixmapType) x11PixmapData->handle(),
                                                 surfaceAttribs.properties());
        x11PixmapData->gl_surface = (void*)surf;
        QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData);
        return surf;
    }

    return EGL_NO_SURFACE;
}
Example #7
0
EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
{
    if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
        qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");

    EGLConfig* targetConfig = 0;

    static EGLConfig defaultVGConfigs[] = {
        QEGL_NO_CONFIG, // 0    Window  Renderable  Translucent
        QEGL_NO_CONFIG, // 1    Window  Renderable  Opaque
        QEGL_NO_CONFIG, // 2    Pixmap  Renderable  Translucent
        QEGL_NO_CONFIG, // 3    Pixmap  Renderable  Opaque
        QEGL_NO_CONFIG, // 4    Pixmap  ReadOnly    Translucent
        QEGL_NO_CONFIG  // 5    Pixmap  ReadOnly    Opaque
    };
    if (api == OpenVG) {
        if (devType == QInternal::Widget) {
            if (options & Translucent)
                targetConfig = &(defaultVGConfigs[0]);
            else
                targetConfig = &(defaultVGConfigs[1]);
        } else if (devType == QInternal::Pixmap) {
            if (options & Renderable) {
                if (options & Translucent)
                    targetConfig = &(defaultVGConfigs[2]);
                else // Opaque
                    targetConfig = &(defaultVGConfigs[3]);
            } else { // Read-only
                if (options & Translucent)
                    targetConfig = &(defaultVGConfigs[4]);
                else // Opaque
                    targetConfig = &(defaultVGConfigs[5]);
            }
        }
    }


    static EGLConfig defaultGLConfigs[] = {
        QEGL_NO_CONFIG, // 0    Window  Renderable  Translucent
        QEGL_NO_CONFIG, // 1    Window  Renderable  Opaque
        QEGL_NO_CONFIG, // 2    PBuffer Renderable  Translucent
        QEGL_NO_CONFIG, // 3    PBuffer Renderable  Opaque
        QEGL_NO_CONFIG, // 4    Pixmap  Renderable  Translucent
        QEGL_NO_CONFIG, // 5    Pixmap  Renderable  Opaque
        QEGL_NO_CONFIG, // 6    Pixmap  ReadOnly    Translucent
        QEGL_NO_CONFIG  // 7    Pixmap  ReadOnly    Opaque
    };
    if (api == OpenGL) {
        if (devType == QInternal::Widget) {
            if (options & Translucent)
                targetConfig = &(defaultGLConfigs[0]);
            else // Opaque
                targetConfig = &(defaultGLConfigs[1]);
        } else if (devType == QInternal::Pbuffer) {
            if (options & Translucent)
                targetConfig = &(defaultGLConfigs[2]);
            else // Opaque
                targetConfig = &(defaultGLConfigs[3]);
        } else if (devType == QInternal::Pixmap) {
            if (options & Renderable) {
                if (options & Translucent)
                    targetConfig = &(defaultGLConfigs[4]);
                else // Opaque
                    targetConfig = &(defaultGLConfigs[5]);
            } else { // ReadOnly
                if (options & Translucent)
                    targetConfig = &(defaultGLConfigs[6]);
                else // Opaque
                    targetConfig = &(defaultGLConfigs[7]);
            }
        }
    }

    if (!targetConfig) {
        qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
        return QEGL_NO_CONFIG;
    }
    if (*targetConfig != QEGL_NO_CONFIG)
        return *targetConfig;


    // We haven't found an EGL config for the target config yet, so do it now:


    // Allow overriding from an environment variable:
    QByteArray configId;
    if (api == OpenVG)
        configId = qgetenv("QT_VG_EGL_CONFIG");
    else
        configId = qgetenv("QT_GL_EGL_CONFIG");
    if (!configId.isEmpty()) {
        // Overridden, so get the EGLConfig for the specified config ID:
        EGLint properties[] = {
            EGL_CONFIG_ID, (EGLint)configId.toInt(),
            EGL_NONE
        };
        EGLint configCount = 0;
        eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
        if (configCount > 0)
            return *targetConfig;
        qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
    }

    QEglProperties configAttribs;
    configAttribs.setRenderableType(api);

    EGLint surfaceType;
    switch (devType) {
        case QInternal::Widget:
            surfaceType = EGL_WINDOW_BIT;
            break;
        case QInternal::Pixmap:
            surfaceType = EGL_PIXMAP_BIT;
            break;
        case QInternal::Pbuffer:
            surfaceType = EGL_PBUFFER_BIT;
            break;
        default:
            qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
            return QEGL_NO_CONFIG;
    };
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
    // For OpenVG, we try to create a surface using a pre-multiplied format if
    // the surface needs to have an alpha channel:
    if (api == OpenVG && (options & Translucent))
        surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT;
#endif
    configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);

#ifdef EGL_BIND_TO_TEXTURE_RGBA
    if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
        if (options & Translucent)
            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
        else
            configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
    }
#endif

    // Add paint engine requirements
    if (api == OpenVG) {
#if !defined(QVG_SCISSOR_CLIP) && defined(EGL_ALPHA_MASK_SIZE)
        configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1);
#endif
    } else {
        // Both OpenGL paint engines need to have stencil and sample buffers
        configAttribs.setValue(EGL_STENCIL_SIZE, 1);
        configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
#ifndef QT_OPENGL_ES_2
        // Additionally, the GL1 engine likes to have a depth buffer for clipping
        configAttribs.setValue(EGL_DEPTH_SIZE, 1);
#endif
    }

    if (options & Translucent)
        configAttribs.setValue(EGL_ALPHA_SIZE, 1);

    *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
    return *targetConfig;
}
QEglContext *QVGEGLWindowSurfaceDirect::ensureContext(QWidget *widget)
{
    QSize newSize = windowSurfaceSize(widget);
    QEglProperties surfaceProps;

#if defined(QVG_RECREATE_ON_SIZE_CHANGE)
#if !defined(QVG_NO_SINGLE_CONTEXT)
    if (context && size != newSize) {
        // The surface size has changed, so we need to recreate it.
        // We can keep the same context and paint engine.
        size = newSize;
        if (isPaintingActive)
            context->doneCurrent();
        context->destroySurface(windowSurface);
#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
        if (isPremultipliedContext(context)) {
            surfaceProps.setValue
                (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
        } else {
            surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
        }
#endif
        windowSurface = context->createSurface(widget, &surfaceProps);
        isPaintingActive = false;
        needToSwap = true;
    }
#else
    if (context && size != newSize) {
        // The surface size has changed, so we need to recreate
        // the EGL context for the widget.  We also need to recreate
        // the surface's paint engine if context sharing is not
        // enabled because we cannot reuse the existing paint objects
        // in the new context.
        qt_vg_destroy_paint_engine(engine);
        engine = 0;
        context->destroySurface(windowSurface);
        qt_vg_destroy_context(context, QInternal::Widget);
        context = 0;
        windowSurface = EGL_NO_SURFACE;
    }
#endif
#endif
    if (!context) {
        // Create a new EGL context and bind it to the widget surface.
        size = newSize;
        context = qt_vg_create_context(widget, QInternal::Widget);
        if (!context)
            return 0;
        // We want a direct to window rendering surface if possible.
#if defined(QVG_DIRECT_TO_WINDOW)
        surfaceProps.setValue(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
#endif
#if defined(EGL_VG_ALPHA_FORMAT_PRE_BIT)
        if (isPremultipliedContext(context)) {
            surfaceProps.setValue
                (EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE);
        } else {
            surfaceProps.removeValue(EGL_VG_ALPHA_FORMAT);
        }
#endif
        EGLSurface surface = context->createSurface(widget, &surfaceProps);
        if (surface == EGL_NO_SURFACE) {
            qt_vg_destroy_context(context, QInternal::Widget);
            context = 0;
            return 0;
        }
        needToSwap = true;
#if defined(QVG_DIRECT_TO_WINDOW)
        // Did we get a direct to window rendering surface?
        EGLint buffer = 0;
        if (eglQueryContext(QEgl::display(), context->context(),
                            EGL_RENDER_BUFFER, &buffer) &&
                buffer == EGL_SINGLE_BUFFER) {
            needToSwap = false;
        }
#endif
        windowSurface = surface;
        isPaintingActive = false;
    }

#if !defined(QVG_NO_PRESERVED_SWAP)
    // Try to force the surface back buffer to preserve its contents.
    if (needToSwap) {
        eglGetError();  // Clear error state first.
        eglSurfaceAttrib(QEgl::display(), windowSurface,
                EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
        if (eglGetError() != EGL_SUCCESS) {
            qWarning("QVG: could not enable preserved swap");
        }
    }
#endif
    return context;
}
static QEglContext *createContext(QPaintDevice *device)
{
    QEglContext *context;

    // Create the context object and open the display.
    context = new QEglContext();
    context->setApi(QEgl::OpenVG);

    // Set the swap interval for the display.
    QByteArray interval = qgetenv("QT_VG_SWAP_INTERVAL");
    if (!interval.isEmpty())
        eglSwapInterval(QEgl::display(), interval.toInt());
    else
        eglSwapInterval(QEgl::display(), 1);

#ifdef EGL_RENDERABLE_TYPE
    // Has the user specified an explicit EGL configuration to use?
    QByteArray configId = qgetenv("QT_VG_EGL_CONFIG");
    if (!configId.isEmpty()) {
        EGLint cfgId = configId.toInt();
        EGLint properties[] = {
            EGL_CONFIG_ID, cfgId,
            EGL_NONE
        };
        EGLint matching = 0;
        EGLConfig cfg;
        if (eglChooseConfig
                    (QEgl::display(), properties, &cfg, 1, &matching) &&
                matching > 0) {
            // Check that the selected configuration actually supports OpenVG
            // and then create the context with it.
            EGLint id = 0;
            EGLint type = 0;
            eglGetConfigAttrib
                (QEgl::display(), cfg, EGL_CONFIG_ID, &id);
            eglGetConfigAttrib
                (QEgl::display(), cfg, EGL_RENDERABLE_TYPE, &type);
            if (cfgId == id && (type & EGL_OPENVG_BIT) != 0) {
                context->setConfig(cfg);
                if (!context->createContext()) {
                    delete context;
                    return 0;
                }
                return context;
            } else {
                qWarning("QT_VG_EGL_CONFIG: %d is not a valid OpenVG configuration", int(cfgId));
            }
        }
    }
#endif

    // Choose an appropriate configuration for rendering into the device.
    QEglProperties configProps;
    configProps.setPaintDeviceFormat(device);
    int redSize = configProps.value(EGL_RED_SIZE);
    if (redSize == EGL_DONT_CARE || redSize == 0)
        configProps.setPixelFormat(QImage::Format_ARGB32);  // XXX
#ifndef QVG_SCISSOR_CLIP
    // If we are using the mask to clip, then explicitly request a mask.
    configProps.setValue(EGL_ALPHA_MASK_SIZE, 1);
#endif
#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT
    configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
                         EGL_VG_ALPHA_FORMAT_PRE_BIT);
    configProps.setRenderableType(QEgl::OpenVG);
    if (!context->chooseConfig(configProps)) {
        // Try again without the "pre" bit.
        configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
        if (!context->chooseConfig(configProps)) {
            delete context;
            return 0;
        }
    }
#else
    configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
    configProps.setRenderableType(QEgl::OpenVG);
    if (!context->chooseConfig(configProps)) {
        delete context;
        return 0;
    }
#endif

    // Construct a new EGL context for the selected configuration.
    if (!context->createContext()) {
        delete context;
        return 0;
    }

    return context;
}
Example #10
0
// Chooses the EGL config and creates the EGL context
bool QGLContext::chooseContext(const QGLContext* shareContext) // almost same as in qgl_x11egl.cpp
{
    Q_D(QGLContext);

    if (!device())
        return false;

    int devType = device()->devType();

    if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
        qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
        return false;
    }

    // Get the display and initialize it.
    if (d->eglContext == 0) {
        d->eglContext = new QEglContext();
        d->ownsEglContext = true;
        d->eglContext->setApi(QEgl::OpenGL);

        if (d->glFormat.samples() == EGL_DONT_CARE) {
            // Allow apps to override ability to use multisampling by setting an environment variable. Eg:
            //   qputenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE", "1");
            // Added to allow camera app to start with limited memory.
            if (!QSymbianGraphicsSystemEx::hasBCM2727() && !qgetenv("QT_SYMBIAN_DISABLE_GL_MULTISAMPLE").toInt()) {
                // Most likely we have hw support for multisampling
                // so let's enable it.
                d->glFormat.setSampleBuffers(1);
                d->glFormat.setSamples(4);
            } else {
                d->glFormat.setSampleBuffers(0);
                d->glFormat.setSamples(0);
            }
        }

	    // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
        // has the alpha channel option set:
        if (devType == QInternal::Widget) {
            QWidget* widget = static_cast<QWidget*>(device());
            if (widget->testAttribute(Qt::WA_TranslucentBackground))
                d->glFormat.setAlpha(true);
        }

        // Construct the configuration we need for this surface.
        QEglProperties configProps;
        configProps.setDeviceType(devType);
        configProps.setPaintDeviceFormat(device());
        configProps.setRenderableType(QEgl::OpenGL);
        configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT|EGL_SWAP_BEHAVIOR_PRESERVED_BIT);

        qt_eglproperties_set_glformat(configProps, d->glFormat);

        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
            delete d->eglContext;
            d->eglContext = 0;
            return false;
        }

        // Create a new context for the configuration.
        QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
        if (!d->eglContext->createContext(eglSharedContext)) {
            delete d->eglContext;
            d->eglContext = 0;
            return false;
        }
        d->sharing = d->eglContext->isSharing();
        if (d->sharing && shareContext)
            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
	}

    // Inform the higher layers about the actual format properties
    qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());

    // Do don't create the EGLSurface for everything.
    //    QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
    //    QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
    //    QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf

    if (devType == QInternal::Widget) {
        if (d->eglSurface != EGL_NO_SURFACE)
            eglDestroySurface(d->eglContext->display(), d->eglSurface);

        d->eglSurface = QEgl::createSurface(device(), d->eglContext->config());

        eglGetError();  // Clear error state first.

#ifdef QGL_NO_PRESERVED_SWAP
        eglSurfaceAttrib(QEgl::display(), d->eglSurface,
                EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);

        if (eglGetError() != EGL_SUCCESS)
            qWarning("QGLContext: could not enable destroyed swap behaviour");
#else
        eglSurfaceAttrib(QEgl::display(), d->eglSurface,
                EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);

        if (eglGetError() != EGL_SUCCESS)
            qWarning("QGLContext: could not enable preserved swap behaviour");
#endif

        setWindowCreated(true);
    }

    return true;
}
Example #11
0
QT_BEGIN_NAMESPACE

#ifdef EGL_BIND_TO_TEXTURE_RGBA
#define QGL_RENDER_TEXTURE 1
#else
#define QGL_RENDER_TEXTURE 0
#endif

bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
{
    // Create the EGL context.
    ctx = new QEglContext();
    ctx->setApi(QEglContext::OpenGL);

    // Open the EGL display.
    if (!ctx->openDisplay(0)) {
        delete ctx;
        ctx = 0;
        return false;
    }

    // Choose an appropriate configuration.  We use the best format
    // we can find, even if it is greater than the requested format.
    // We try for a pbuffer that is capable of texture rendering if possible.
    QEglProperties configProps;
    qt_egl_set_format(configProps, QInternal::Pbuffer, f);
    configProps.setRenderableType(ctx->api());
    bool ok = false;
#if QGL_RENDER_TEXTURE
    textureFormat = EGL_TEXTURE_RGBA;
    configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
    ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
    if (!ok) {
        // Try again with RGB texture rendering.
        textureFormat = EGL_TEXTURE_RGB;
        configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA);
        configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
        ok = ctx->chooseConfig(configProps, QEglContext::BestPixelFormat);
        if (!ok) {
            // One last try for a pbuffer with no texture rendering.
            configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB);
            textureFormat = EGL_NONE;
        }
    }
#else
    textureFormat = EGL_NONE;
#endif
    if (!ok) {
        if (!ctx->chooseConfig(configProps, QEglContext::BestPixelFormat)) {
            delete ctx;
            ctx = 0;
            return false;
        }
    }

    // Retrieve the actual format properties.
    qt_egl_update_format(*ctx, format);

    // Create the attributes needed for the pbuffer.
    QEglProperties attribs;
    attribs.setValue(EGL_WIDTH, size.width());
    attribs.setValue(EGL_HEIGHT, size.height());
#if QGL_RENDER_TEXTURE
    if (textureFormat != EGL_NONE) {
        attribs.setValue(EGL_TEXTURE_FORMAT, textureFormat);
        attribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
    }
#endif

    // Create the pbuffer surface.
    pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties());
#if QGL_RENDER_TEXTURE
    if (pbuf == EGL_NO_SURFACE && textureFormat != EGL_NONE) {
        // Try again with texture rendering disabled.
        textureFormat = EGL_NONE;
        attribs.removeValue(EGL_TEXTURE_FORMAT);
        attribs.removeValue(EGL_TEXTURE_TARGET);
        pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties());
    }
#endif
    if (pbuf == EGL_NO_SURFACE) {
        qWarning() << "QGLPixelBufferPrivate::init(): Unable to create EGL pbuffer surface:" << QEglContext::errorString(eglGetError());
        return false;
    }
    ctx->setSurface(pbuf);

    // Create a new context for the configuration.
    QEglContext *shareContext = 0;
    if (shareWidget && shareWidget->d_func()->glcx)
        shareContext = shareWidget->d_func()->glcx->d_func()->eglContext;
    if (!ctx->createContext(shareContext)) {
        delete ctx;
        ctx = 0;
        return false;
    }

    return true;
}
Example #12
0
// Chooses the EGL config and creates the EGL context
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
    Q_D(QGLContext);

    if (!device())
        return false;

    int devType = device()->devType();

    QX11PixmapData *x11PixmapData = 0;
    if (devType == QInternal::Pixmap) {
        QPixmapData *pmd = static_cast<QPixmap*>(device())->data_ptr().data();
        if (pmd->classId() == QPixmapData::X11Class)
            x11PixmapData = static_cast<QX11PixmapData*>(pmd);
        else {
            // TODO: Replace the pixmap's data with a new QX11PixmapData
            qWarning("WARNING: Creating a QGLContext on a QPixmap is only supported for X11 pixmap backend");
            return false;
        }
    } else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
        qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
        return false;
    }

    // Only create the eglContext if we don't already have one:
    if (d->eglContext == 0) {
        d->eglContext = new QEglContext();
        d->ownsEglContext = true;
        d->eglContext->setApi(QEgl::OpenGL);

        // If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
        // has the alpha channel option set:
        if (devType == QInternal::Widget) {
            QWidget* widget = static_cast<QWidget*>(device());
            if (widget->testAttribute(Qt::WA_TranslucentBackground))
                d->glFormat.setAlpha(true);
        }

        // Construct the configuration we need for this surface.
        QEglProperties configProps;
        configProps.setDeviceType(devType);
        configProps.setRenderableType(QEgl::OpenGL);
        qt_eglproperties_set_glformat(configProps, d->glFormat);

        // Set buffer preserved for regular QWidgets, QGLWidgets are ok with either preserved or destroyed:
        if ((devType == QInternal::Widget) && qobject_cast<QGLWidget*>(static_cast<QWidget*>(device())) == 0)
            configProps.setValue(EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);

        if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
            delete d->eglContext;
            d->eglContext = 0;
            return false;
        }

        // Create a new context for the configuration.
        QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
        if (!d->eglContext->createContext(eglSharedContext)) {
            delete d->eglContext;
            d->eglContext = 0;
            return false;
        }
        d->sharing = d->eglContext->isSharing();
        if (d->sharing && shareContext)
            const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
    }

    // Inform the higher layers about the actual format properties
    qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());

    // Do don't create the EGLSurface for everything.
    //    QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
    //    QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
    //    QPixmap - yes, create the EGLSurface but store it in QX11PixmapData::gl_surface
    //    QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf

    if (devType == QInternal::Widget) {
        if (d->eglSurface != EGL_NO_SURFACE)
            eglDestroySurface(d->eglContext->display(), d->eglSurface);
        // extraWindowSurfaceCreationProps default to NULL unless were specifically set before
        d->eglSurface = QEgl::createSurface(device(), d->eglContext->config(), d->extraWindowSurfaceCreationProps);
        XFlush(X11->display);
        setWindowCreated(true);
    }

    if (x11PixmapData) {
        // TODO: Actually check to see if the existing surface can be re-used
        if (x11PixmapData->gl_surface)
            eglDestroySurface(d->eglContext->display(), (EGLSurface)x11PixmapData->gl_surface);

        x11PixmapData->gl_surface = (void*)QEgl::createSurface(device(), d->eglContext->config());
    }

    return true;
}