📄 qgl_x11.cpp
字号:
public: QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, const QGLWidget* shareWidget=0);protected: void initializeGL(); void paintGL(); void resizeGL(int w, int h);private: QGLWidget* realWidget;private: Q_DISABLE_COPY(QGLOverlayWidget)};QGLOverlayWidget::QGLOverlayWidget(const QGLFormat& format, QGLWidget* parent, const QGLWidget* shareWidget) : QGLWidget(format, parent, shareWidget ? shareWidget->d_func()->olw : 0){ setAttribute(Qt::WA_X11OpenGLOverlay); realWidget = parent;}void QGLOverlayWidget::initializeGL(){ QColor transparentColor = context()->overlayTransparentColor(); if (transparentColor.isValid()) qglClearColor(transparentColor); else qWarning("QGLOverlayWidget::initializeGL(): Could not get transparent color"); realWidget->initializeOverlayGL();}void QGLOverlayWidget::resizeGL(int w, int h){ glViewport(0, 0, w, h); realWidget->resizeOverlayGL(w, h);}void QGLOverlayWidget::paintGL(){ realWidget->paintOverlayGL();}#undef Bool#include "qgl_x11.moc"/***************************************************************************** QGLWidget UNIX/GLX-specific code *****************************************************************************/void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget){ Q_Q(QGLWidget); initContext(context, shareWidget); olw = 0; if (q->isValid() && context->format().hasOverlay()) { QString olwName = q->objectName(); olwName += QLatin1String("-QGL_internal_overlay_widget"); olw = new QGLOverlayWidget(QGLFormat::defaultOverlayFormat(), q, shareWidget); olw->setObjectName(olwName); if (olw->isValid()) { olw->setAutoBufferSwap(false); olw->setFocusProxy(q); } else { delete olw; olw = 0; glcx->d_func()->glFormat.setOverlay(false); } }}bool QGLWidgetPrivate::renderCxPm(QPixmap* pm){ Q_Q(QGLWidget); if (((XVisualInfo*)glcx->d_func()->vi)->depth != pm->depth()) return false; GLXPixmap glPm;#if defined(GLX_MESA_pixmap_colormap) && defined(QGL_USE_MESA_EXT) glPm = glXCreateGLXPixmapMESA(X11->display, (XVisualInfo*)glcx->vi, (Pixmap)pm->handle(), choose_cmap(pm->X11->display, (XVisualInfo*)glcx->vi));#else glPm = (quint32)glXCreateGLXPixmap(X11->display, (XVisualInfo*)glcx->d_func()->vi, (Pixmap)pm->handle());#endif if (!glXMakeCurrent(X11->display, glPm, (GLXContext)glcx->d_func()->cx)) { glXDestroyGLXPixmap(X11->display, glPm); return false; } glDrawBuffer(GL_FRONT); if (!glcx->initialized()) q->glInit(); q->resizeGL(pm->width(), pm->height()); q->paintGL(); glFlush(); q->makeCurrent(); glXDestroyGLXPixmap(X11->display, glPm); q->resizeGL(q->width(), q->height()); return true;}/*! \internal Free up any allocated colormaps. This fn is only called for top-level widgets.*/void QGLWidgetPrivate::cleanupColormaps(){ if (!cmap.handle()) { return; } else { XFreeColormap(X11->display, (Colormap) cmap.handle()); cmap.setHandle(0); }}/*! \reimp */bool QGLWidget::event(QEvent *e){ Q_D(QGLWidget); // prevents X errors on some systems, where we get a flush to a // hidden widget if (e->type() == QEvent::Hide) { makeCurrent(); glFinish(); doneCurrent(); } else if (e->type() == QEvent::ParentChange) { if (d->glcx->d_func()->screen != d->xinfo.screen()) { setContext(new QGLContext(d->glcx->requestedFormat(), this)); // ### recreating the overlay isn't supported atm } } return QWidget::event(e);}void QGLWidget::setMouseTracking(bool enable){ Q_D(QGLWidget); if (d->olw) d->olw->setMouseTracking(enable); QWidget::setMouseTracking(enable);}void QGLWidget::resizeEvent(QResizeEvent *){ Q_D(QGLWidget); if (!isValid()) return; makeCurrent(); if (!d->glcx->initialized()) glInit(); glXWaitX(); resizeGL(width(), height()); if (d->olw) d->olw->setGeometry(rect());}const QGLContext* QGLWidget::overlayContext() const{ Q_D(const QGLWidget); if (d->olw) return d->olw->context(); else return 0;}void QGLWidget::makeOverlayCurrent(){ Q_D(QGLWidget); if (d->olw) d->olw->makeCurrent();}void QGLWidget::updateOverlayGL(){ Q_D(QGLWidget); if (d->olw) d->olw->updateGL();}/*! \internal Sets a new QGLContext, \a context, for this QGLWidget, using the shared context, \a shareContext. If \a deleteOldContext is true, the original context is deleted; otherwise it is overridden.*/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 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; } bool visible = isVisible(); if (visible) hide(); XVisualInfo *vi = (XVisualInfo*)d->glcx->d_func()->vi; XSetWindowAttributes a; QColormap colmap = QColormap::instance(vi->screen); a.colormap = choose_cmap(QX11Info::display(), vi); // find best colormap a.background_pixel = colmap.pixel(palette().color(backgroundRole())); a.border_pixel = colmap.pixel(Qt::black); Window p = RootWindow(X11->display, vi->screen); if (parentWidget()) p = parentWidget()->winId(); Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(), 0, vi->depth, InputOutput, vi->visual, CWBackPixel|CWBorderPixel|CWColormap, &a); Window *cmw; Window *cmwret; int count; if (XGetWMColormapWindows(X11->display, window()->winId(), &cmwret, &count)) { cmw = new Window[count+1]; memcpy((char *)cmw, (char *)cmwret, sizeof(Window)*count); XFree((char *)cmwret); int i; for (i=0; i<count; i++) { if (cmw[i] == winId()) { // replace old window cmw[i] = w; break; } } if (i >= count) // append new window cmw[count++] = w; } else { count = 1; cmw = new Window[count]; cmw[0] = w; }#if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT) if (oldcx && oldcx->windowCreated()) glXReleaseBuffersMESA(X11->display, winId());#endif if (deleteOldContext) delete oldcx; oldcx = 0; if (testAttribute(Qt::WA_WState_Created)) create(w); else d->createWinId(w); XSetWMColormapWindows(X11->display, window()->winId(), cmw, count); delete [] cmw; // calling QWidget::create() will always result in a new paint // engine being created - get rid of it and replace it with our // own if (visible) show(); XFlush(X11->display); d->glcx->setWindowCreated(true);}const QGLColormap & QGLWidget::colormap() const{ Q_D(const QGLWidget); return d->cmap;}/*\internal Store color values in the given colormap.*/static void qStoreColors(QWidget * tlw, Colormap cmap, const QGLColormap & cols){ Q_UNUSED(tlw); XColor c; QRgb color; for (int i = 0; i < cols.size(); i++) { color = cols.entryRgb(i); c.pixel = i; c.red = (ushort)((qRed(color) / 255.0) * 65535.0 + 0.5); c.green = (ushort)((qGreen(color) / 255.0) * 65535.0 + 0.5); c.blue = (ushort)((qBlue(color) / 255.0) * 65535.0 + 0.5); c.flags = DoRed | DoGreen | DoBlue; XStoreColor(X11->display, cmap, &c); }}/*\internal Check whether the given visual supports dynamic colormaps or not.*/static bool qCanAllocColors(QWidget * w){ bool validVisual = false; int numVisuals; long mask; XVisualInfo templ; XVisualInfo * visuals; VisualID id = XVisualIDFromVisual((Visual *) w->window()->x11Info().visual()); mask = VisualScreenMask; templ.screen = w->x11Info().screen(); visuals = XGetVisualInfo(X11->display, mask, &templ, &numVisuals); for (int i = 0; i < numVisuals; i++) { if (visuals[i].visualid == id) { switch (visuals[i].c_class) { case TrueColor: case StaticColor: case StaticGray: case XGrayScale: validVisual = false; break; case DirectColor: case PseudoColor: validVisual = true; break; } break; } } XFree(visuals); if (!validVisual) return false; return true;}void QGLWidget::setColormap(const QGLColormap & c){ Q_D(QGLWidget); QWidget * tlw = window(); // must return a valid widget d->cmap = c; if (!d->cmap.handle()) return; if (!qCanAllocColors(this)) { qWarning("QGLWidget::setColormap: Cannot create a read/write " "colormap for this visual"); return; } // If the child GL widget is not of the same visual class as the // toplevel widget we will get in trouble.. Window wid = tlw->winId(); Visual * vis = (Visual *) tlw->x11Info().visual();; VisualID cvId = XVisualIDFromVisual((Visual *) x11Info().visual()); VisualID tvId = XVisualIDFromVisual((Visual *) tlw->x11Info().visual()); if (cvId != tvId) { wid = winId(); vis = (Visual *) x11Info().visual(); } if (!d->cmap.handle()) // allocate a cmap if necessary d->cmap.setHandle(XCreateColormap(X11->display, wid, vis, AllocAll)); qStoreColors(this, (Colormap) d->cmap.handle(), c); XSetWindowColormap(X11->display, wid, (Colormap) d->cmap.handle()); // tell the wm that this window has a special colormap Window * cmw; Window * cmwret; int count; if (XGetWMColormapWindows(X11->display, tlw->winId(), &cmwret, &count)) { cmw = new Window[count+1]; memcpy((char *) cmw, (char *) cmwret, sizeof(Window) * count); XFree((char *) cmwret); int i; for (i = 0; i < count; i++) { if (cmw[i] == winId()) { break; } } if (i >= count) // append new window only if not in the list cmw[count++] = winId(); } else { count = 1; cmw = new Window[count]; cmw[0] = winId(); } XSetWMColormapWindows(X11->display, tlw->winId(), cmw, count); delete [] cmw;}void QGLExtensions::init(){ static bool init_done = false; if (init_done) return; init_done = true; QGLWidget dmy; dmy.makeCurrent(); init_extensions(); // nvidia 9x.xx unix drivers contain a bug which requires us to call glFinish before releasing an fbo // to avoid painting artifacts const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION))); const int pos = versionString.indexOf("NVIDIA"); if (pos >= 0) { const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat(); nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -