Example #1
0
uint QGLContext::colorIndex(const QColor& c) const
{
    Q_D(const QGLContext);
    int screen = ((XVisualInfo *)d->vi)->screen;
    QColormap colmap = QColormap::instance(screen);
    if (isValid()) {
        if (format().plane() && c == Qt::transparent) {
            return qt_transparent_pixel(((XVisualInfo *)d->vi)->visualid,
                                        ((XVisualInfo *)d->vi)->screen);
        }
        if (((XVisualInfo*)d->vi)->visualid ==
             XVisualIDFromVisual((Visual *) QX11Info::appVisual(screen)))
            return colmap.pixel(c);                // We're using QColor's cmap

        XVisualInfo *info = (XVisualInfo *) d->vi;
        CMapEntryHash *hash = cmap_handler()->cmap_hash;
        CMapEntryHash::ConstIterator it = hash->constFind(long(info->visualid)
                + (info->screen * 256));
        QCMapEntry *x = 0;
        if (it != hash->constEnd())
            x = it.value();
        if (x && !x->alloc) {                // It's a standard colormap
            int rf = (int)(((float)c.red() * (x->scmap.red_max+1))/256.0);
            int gf = (int)(((float)c.green() * (x->scmap.green_max+1))/256.0);
            int bf = (int)(((float)c.blue() * (x->scmap.blue_max+1))/256.0);
            uint p = x->scmap.base_pixel
                     + (rf * x->scmap.red_mult)
                     + (gf * x->scmap.green_mult)
                     + (bf * x->scmap.blue_mult);
            return p;
        } else {
            QMap<int, QRgb> &cmap = (*cmap_handler()->qglcmap_hash)[(long)info->visualid];

            // already in the map?
            QRgb target = c.rgb();
            QMap<int, QRgb>::Iterator it = cmap.begin();
            for (; it != cmap.end(); ++it) {
                if ((*it) == target)
                    return it.key();
            }

            // need to alloc color
            unsigned long plane_mask[2];
            unsigned long color_map_entry;
            if (!XAllocColorCells (QX11Info::display(), x->cmap, true, plane_mask, 0,
                                   &color_map_entry, 1))
                return colmap.pixel(c);

            XColor col;
            col.flags = DoRed | DoGreen | DoBlue;
            col.pixel = color_map_entry;
            col.red   = (ushort)((qRed(c.rgb()) / 255.0) * 65535.0 + 0.5);
            col.green = (ushort)((qGreen(c.rgb()) / 255.0) * 65535.0 + 0.5);
            col.blue  = (ushort)((qBlue(c.rgb()) / 255.0) * 65535.0 + 0.5);
            XStoreColor(QX11Info::display(), x->cmap, &col);

            cmap.insert(color_map_entry, target);
            return color_map_entry;
        }
    }
    return 0;
}
Example #2
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 #3
0
void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
{
    Q_D(QGLWidget);
    if (context == 0) {
        qWarning("QGLWidget::setContext: Cannot set null context");
        return;
    }
    if (!context->deviceIsPixmap() && context->device() != this) {
        qWarning("QGLWidget::setContext: Context must refer to this widget");
        return;
    }

    if (d->glcx)
        d->glcx->doneCurrent();
    QGLContext* oldcx = d->glcx;
    d->glcx = context;

    if (parentWidget()) {
        // force creation of delay-created widgets
        parentWidget()->winId();
        if (parentWidget()->x11Info().screen() != x11Info().screen())
            d_func()->xinfo = parentWidget()->d_func()->xinfo;
    }

    bool visible = isVisible();
    if (visible)
        hide();

    XVisualInfo vi;

    int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi);
    if (err == 0) {
        qWarning("Error: Couldn't get a matching X visual for format");
        return;
    }

    XSetWindowAttributes a;

    Window p = RootWindow(X11->display, vi.screen);
    if (parentWidget())
        p = parentWidget()->winId();

    QColormap colmap = QColormap::instance(vi.screen);
    a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
    a.border_pixel = colmap.pixel(Qt::black);

    Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
                             0, vi.depth, InputOutput, vi.visual,
                             CWBackPixel|CWBorderPixel, &a);

    if (deleteOldContext)
        delete oldcx;
    oldcx = 0;

    create(w); // Create with the ID of the window we've just created

    d->eglSurfaceWindowId = w; // Remember the window id we created the surface for

    if (visible)
        show();

    bool createFailed = false;
    if (!d->glcx->isValid()) {
        if (!d->glcx->create(shareContext ? shareContext : oldcx))
            createFailed = true;
    }
    if (createFailed) {
        if (deleteOldContext)
            delete oldcx;
        return;
    }

    if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
        if (deleteOldContext)
            delete oldcx;
        return;
    }

    d->glcx->setWindowCreated(true);
}