📄 qgl_x11.cpp
字号:
fmt.setDoubleBuffer(true); tryDouble = false; triedDouble = true; continue; } else if (triedDouble) { fmt.setDoubleBuffer(false); triedDouble = false; } if (!triedSample && fmt.sampleBuffers()) { fmt.setSampleBuffers(false); triedSample = true; continue; } if (fmt.stereo()) { fmt.setStereo(false); continue; } if (fmt.accum()) { fmt.setAccum(false); continue; } if (fmt.stencil()) { fmt.setStencil(false); continue; } if (fmt.alpha()) { fmt.setAlpha(false); continue; } if (fmt.depth()) { fmt.setDepth(false); continue; } if (fmt.doubleBuffer()) { fmt.setDoubleBuffer(false); continue; } fail = true; } d->glFormat = fmt; return vis;}/*! \internal \bold{X11 only:} This virtual function chooses a visual that matches the OpenGL \link format() format\endlink. Reimplement this function in a subclass if you need a custom visual. \sa chooseContext()*/void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth){ Q_D(QGLContext); int spec[40]; int i = 0; spec[i++] = GLX_LEVEL; spec[i++] = f.plane(); const QX11Info *xinfo = qt_x11Info(d->paintDevice);#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info) static bool useTranspExt = false; static bool useTranspExtChecked = false; if (f.plane() && !useTranspExtChecked && d->paintDevice) { QByteArray estr(glXQueryExtensionsString(xinfo->display(), xinfo->screen())); useTranspExt = estr.contains("GLX_EXT_visual_info"); //# (A bit simplistic; that could theoretically be a substring) if (useTranspExt) { QByteArray cstr(glXGetClientString(xinfo->display(), GLX_VENDOR)); useTranspExt = !cstr.contains("Xi Graphics"); // bug workaround if (useTranspExt) { // bug workaround - some systems (eg. FireGL) refuses to return an overlay // visual if the GLX_TRANSPARENT_TYPE_EXT attribute is specified, even if // the implementation supports transparent overlays int tmpSpec[] = { GLX_LEVEL, f.plane(), GLX_TRANSPARENT_TYPE_EXT, f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT, XNone }; XVisualInfo * vinf = glXChooseVisual(xinfo->display(), xinfo->screen(), tmpSpec); if (!vinf) { useTranspExt = false; } } } useTranspExtChecked = true; } if (f.plane() && useTranspExt) { // Required to avoid non-transparent overlay visual(!) on some systems spec[i++] = GLX_TRANSPARENT_TYPE_EXT; spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; }#endif if (f.doubleBuffer()) spec[i++] = GLX_DOUBLEBUFFER; if (f.depth()) { spec[i++] = GLX_DEPTH_SIZE; spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize(); } if (f.stereo()) { spec[i++] = GLX_STEREO; } if (f.stencil()) { spec[i++] = GLX_STENCIL_SIZE; spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize(); } if (f.rgba()) { spec[i++] = GLX_RGBA; spec[i++] = GLX_RED_SIZE; spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize(); spec[i++] = GLX_GREEN_SIZE; spec[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize(); spec[i++] = GLX_BLUE_SIZE; spec[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize(); if (f.alpha()) { spec[i++] = GLX_ALPHA_SIZE; spec[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize(); } if (f.accum()) { spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); if (f.alpha()) { spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize(); } } } else { spec[i++] = GLX_BUFFER_SIZE; spec[i++] = bufDepth; } if (f.sampleBuffers()) { spec[i++] = GLX_SAMPLE_BUFFERS_ARB; spec[i++] = 1; spec[i++] = GLX_SAMPLES_ARB; spec[i++] = f.samples() == -1 ? 4 : f.samples(); } spec[i] = XNone; return glXChooseVisual(xinfo->display(), xinfo->screen(), spec);}void QGLContext::reset(){ Q_D(QGLContext); if (!d->valid) return; const QX11Info *xinfo = qt_x11Info(d->paintDevice); doneCurrent(); if (d->gpm) glXDestroyGLXPixmap(xinfo->display(), (GLXPixmap)d->gpm); d->gpm = 0; glXDestroyContext(xinfo->display(), (GLXContext)d->cx); if (d->vi) XFree(d->vi); d->vi = 0; d->cx = 0; d->crWin = false; d->sharing = false; d->valid = false; d->transpColor = QColor(); d->initDone = false; qgl_share_reg()->removeShare(this);}void QGLContext::makeCurrent(){ Q_D(QGLContext); if (!d->valid) { qWarning("QGLContext::makeCurrent(): Cannot make invalid context current."); return; } const QX11Info *xinfo = qt_x11Info(d->paintDevice); bool ok = true; if (d->paintDevice->devType() == QInternal::Pixmap) { ok = glXMakeCurrent(xinfo->display(), (GLXPixmap)d->gpm, (GLXContext)d->cx); } else if (d->paintDevice->devType() == QInternal::Pbuffer) { ok = glXMakeCurrent(xinfo->display(), (GLXPbuffer)d->pbuf, (GLXContext)d->cx); } else if (d->paintDevice->devType() == QInternal::Widget) { ok = glXMakeCurrent(xinfo->display(), ((QWidget *)d->paintDevice)->winId(), (GLXContext)d->cx); } if (!ok) qWarning("QGLContext::makeCurrent(): Failed."); if (ok) { if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) qgl_context_storage.setLocalData(new QGLThreadContext); if (qgl_context_storage.hasLocalData()) qgl_context_storage.localData()->context = this; currentCtx = this; }}void QGLContext::doneCurrent(){ Q_D(QGLContext); glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0); if (qgl_context_storage.hasLocalData()) qgl_context_storage.localData()->context = 0; currentCtx = 0;}void QGLContext::swapBuffers() const{ Q_D(const QGLContext); if (!d->valid) return; if (!deviceIsPixmap()) glXSwapBuffers(qt_x11Info(d->paintDevice)->display(), static_cast<QWidget *>(d->paintDevice)->winId());}QColor QGLContext::overlayTransparentColor() const{ if (isValid()) return Qt::transparent; return QColor(); // Invalid color}static uint qt_transparent_pixel(VisualID id, int screen){ for (int i = 0; i < trans_colors.size(); i++) { if (trans_colors[i].vis == id && trans_colors[i].screen == screen) return trans_colors[i].color; } return 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;}#ifndef QT_NO_FONTCONFIG/*! \internal This is basically a substitute for glxUseXFont() which can only handle XLFD fonts. This version relies on freetype to render the glyphs, but it works with all fonts that fontconfig provides - both antialiased and aliased bitmap and outline fonts.*/static void qgl_use_font(QFontEngineFT *engine, int first, int count, int listBase){ GLfloat color[4]; glGetFloatv(GL_CURRENT_COLOR, color); // save the pixel unpack state GLint gl_swapbytes, gl_lsbfirst, gl_rowlength, gl_skiprows, gl_skippixels, gl_alignment; glGetIntegerv (GL_UNPACK_SWAP_BYTES, &gl_swapbytes); glGetIntegerv (GL_UNPACK_LSB_FIRST, &gl_lsbfirst); glGetIntegerv (GL_UNPACK_ROW_LENGTH, &gl_rowlength); glGetIntegerv (GL_UNPACK_SKIP_ROWS, &gl_skiprows); glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &gl_skippixels); glGetIntegerv (GL_UNPACK_ALIGNMENT, &gl_alignment); glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); const bool antialiased = engine->drawAntialiased(); FT_Face face = engine->lockFace(); // start generating font glyphs for (int i = first; i < count; ++i) { int list = listBase + i; GLfloat x0, y0, dx, dy; FT_Error err; err = FT_Load_Glyph(face, FT_Get_Char_Index(face, i), FT_LOAD_DEFAULT); if (err) { qDebug("failed loading glyph %d from font", i); Q_ASSERT(!err); } err = FT_Render_Glyph(face->glyph, (antialiased ? ft_render_mode_normal : ft_render_mode_mono)); if (err) { qDebug("failed rendering glyph %d from font", i); Q_ASSERT(!err); } FT_Bitmap bm = face->glyph->bitmap; x0 = face->glyph->metrics.horiBearingX >> 6; y0 = (face->glyph->metrics.height - face->glyph->metrics.horiBearingY) >> 6; dx = face->glyph->metrics.horiAdvance >> 6; dy = 0; int sz = bm.pitch * bm.rows; uint *aa_glyph = 0; uchar *ua_glyph = 0; if (antialiased) aa_glyph = new uint[sz]; else ua_glyph = new uchar[sz]; // convert to GL format for (int y = 0; y < bm.rows; ++y) { for (int x = 0; x < bm.pitch; ++x) { int c1 = y*bm.pitch + x; int c2 = (bm.rows - y - 1) > 0 ? (bm.rows-y-1)*bm.pitch + x : x; if (antialiased) { aa_glyph[c1] = (int(color[0]*255) << 24) | (int(color[1]*255) << 16) | (int(color[2]*255) << 8) | bm.buffer[c2]; } else { ua_glyph[c1] = bm.buffer[c2]; } } } glNewList(list, GL_COMPILE); if (antialiased) { // calling glBitmap() is just a trick to move the current // raster pos, since glGet*() won't work in display lists glBitmap(0, 0, 0, 0, x0, -y0, 0); glDrawPixels(bm.pitch, bm.rows, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, aa_glyph); glBitmap(0, 0, 0, 0, dx-x0, y0, 0); } else { glBitmap(bm.pitch*8, bm.rows, -x0, y0, dx, dy, ua_glyph); } glEndList(); antialiased ? delete[] aa_glyph : delete[] ua_glyph; } engine->unlockFace(); // restore pixel unpack settings glPixelStorei(GL_UNPACK_SWAP_BYTES, gl_swapbytes); glPixelStorei(GL_UNPACK_LSB_FIRST, gl_lsbfirst); glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_rowlength); glPixelStorei(GL_UNPACK_SKIP_ROWS, gl_skiprows); glPixelStorei(GL_UNPACK_SKIP_PIXELS, gl_skippixels); glPixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment);}#endif#undef dvoid QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase){ QFont f(fnt); QFontEngine *engine = f.d->engineForScript(QUnicodeTables::Common); if (engine->type() == QFontEngine::Multi) engine = static_cast<QFontEngineMulti *>(engine)->engine(0);#ifndef QT_NO_FONTCONFIG if(engine->type() == QFontEngine::Freetype) { qgl_use_font(static_cast<QFontEngineFT *>(engine), 0, 256, listBase); return; }#endif // glXUseXFont() only works with XLFD font structures and a few GL // drivers crash if 0 is passed as the font handle f.setStyleStrategy(QFont::OpenGLCompatible); if (f.handle() && engine->type() == QFontEngine::XLFD) glXUseXFont(static_cast<Font>(f.handle()), 0, 256, listBase);}/*! Returns a function pointer to the GL extension function passed in \a proc. 0 is returned if a pointer to the function could not be obtained.*/void *QGLContext::getProcAddress(const QString &proc) const{ typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; static bool resolved = false; if (resolved && !glXGetProcAddressARB) return 0; if (!glXGetProcAddressARB) { QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS))); if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) { extern const QString qt_gl_library_name(); QLibrary lib(qt_gl_library_name()); glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); } resolved = true; } if (!glXGetProcAddressARB) return 0; return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data()));}/***************************************************************************** QGLOverlayWidget (Internal overlay class for X11) *****************************************************************************/class QGLOverlayWidget : public QGLWidget{ Q_OBJECT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -