void GlxBackend::init() { initGLX(); // Require at least GLX 1.3 if (!hasGLXVersion(1, 3)) { setFailed(QStringLiteral("Requires at least GLX 1.3")); return; } initVisualDepthHashTable(); if (!initBuffer()) { setFailed(QStringLiteral("Could not initialize the buffer")); return; } if (!initRenderingContext()) { setFailed(QStringLiteral("Could not initialize rendering context")); return; } // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(GlxPlatformInterface); if (GLPlatform::instance()->driver() == Driver_Intel) options->setUnredirectFullscreen(false); // bug #252817 options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen glPlatform->printResults(); initGL(GlxPlatformInterface); // Check whether certain features are supported m_haveMESACopySubBuffer = hasGLExtension(QByteArrayLiteral("GLX_MESA_copy_sub_buffer")); m_haveMESASwapControl = hasGLExtension(QByteArrayLiteral("GLX_MESA_swap_control")); m_haveEXTSwapControl = hasGLExtension(QByteArrayLiteral("GLX_EXT_swap_control")); m_haveSGISwapControl = hasGLExtension(QByteArrayLiteral("GLX_SGI_swap_control")); // only enable Intel swap event if env variable is set, see BUG 342582 m_haveINTELSwapEvent = hasGLExtension(QByteArrayLiteral("GLX_INTEL_swap_event")) && qgetenv("KWIN_USE_INTEL_SWAP_EVENT") == QByteArrayLiteral("1"); if (m_haveINTELSwapEvent) { m_swapEventFilter = std::make_unique<SwapEventFilter>(window, glxWindow); glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl || m_haveSGISwapControl; setSupportsBufferAge(false); if (hasGLExtension(QByteArrayLiteral("GLX_EXT_buffer_age"))) { const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); if (useBufferAge != "0") setSupportsBufferAge(true); } setSyncsToVBlank(false); setBlocksForRetrace(false); haveWaitSync = false; gs_tripleBufferNeedsDetection = false; m_swapProfiler.init(); const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; if (wantSync && glXIsDirect(display(), ctx)) { if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable setSwapInterval(1); setSyncsToVBlank(true); const QByteArray tripleBuffer = qgetenv("KWIN_TRIPLE_BUFFER"); if (!tripleBuffer.isEmpty()) { setBlocksForRetrace(qstrcmp(tripleBuffer, "0") == 0); gs_tripleBufferUndetected = false; } gs_tripleBufferNeedsDetection = gs_tripleBufferUndetected; } else if (hasGLExtension(QByteArrayLiteral("GLX_SGI_video_sync"))) { unsigned int sync; if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) { setSyncsToVBlank(true); setBlocksForRetrace(true); haveWaitSync = true; } else qCWarning(KWIN_CORE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; } else qCWarning(KWIN_CORE) << "NO VSYNC! neither glSwapInterval nor glXWaitVideoSync are supported"; } else { // disable v-sync (if possible) setSwapInterval(0); } if (glPlatform->isVirtualBox()) { // VirtualBox does not support glxQueryDrawable // this should actually be in kwinglutils_funcs, but QueryDrawable seems not to be provided by an extension // and the GLPlatform has not been initialized at the moment when initGLX() is called. glXQueryDrawable = NULL; } setIsDirectRendering(bool(glXIsDirect(display(), ctx))); qCDebug(KWIN_CORE) << "Direct rendering:" << isDirectRendering(); }
void GlxBackend::init() { initGLX(); // require at least GLX 1.3 if (!hasGLXVersion(1, 3)) { setFailed(QStringLiteral("Requires at least GLX 1.3")); return; } if (!initDrawableConfigs()) { setFailed(QStringLiteral("Could not initialize the drawable configs")); return; } if (!initBuffer()) { setFailed(QStringLiteral("Could not initialize the buffer")); return; } if (!initRenderingContext()) { setFailed(QStringLiteral("Could not initialize rendering context")); return; } // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(GlxPlatformInterface); if (GLPlatform::instance()->driver() == Driver_Intel) options->setUnredirectFullscreen(false); // bug #252817 options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen glPlatform->printResults(); initGL(GlxPlatformInterface); // Check whether certain features are supported haveSwapInterval = glXSwapIntervalMESA || glXSwapIntervalEXT || glXSwapIntervalSGI; setSupportsBufferAge(false); if (hasGLExtension("GLX_EXT_buffer_age")) { const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); if (useBufferAge != "0") setSupportsBufferAge(true); } setSyncsToVBlank(false); setBlocksForRetrace(false); haveWaitSync = false; gs_tripleBufferNeedsDetection = false; m_swapProfiler.init(); const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; if (wantSync && glXIsDirect(display(), ctx)) { if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable setSwapInterval(1); setSyncsToVBlank(true); const QByteArray tripleBuffer = qgetenv("KWIN_TRIPLE_BUFFER"); if (!tripleBuffer.isEmpty()) { setBlocksForRetrace(qstrcmp(tripleBuffer, "0") == 0); gs_tripleBufferUndetected = false; } gs_tripleBufferNeedsDetection = gs_tripleBufferUndetected; } else if (glXGetVideoSync) { unsigned int sync; if (glXGetVideoSync(&sync) == 0 && glXWaitVideoSync(1, 0, &sync) == 0) { setSyncsToVBlank(true); setBlocksForRetrace(true); haveWaitSync = true; } else qWarning() << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; } else qWarning() << "NO VSYNC! neither glSwapInterval nor glXWaitVideoSync are supported"; } else { // disable v-sync (if possible) setSwapInterval(0); } if (glPlatform->isVirtualBox()) { // VirtualBox does not support glxQueryDrawable // this should actually be in kwinglutils_funcs, but QueryDrawable seems not to be provided by an extension // and the GLPlatform has not been initialized at the moment when initGLX() is called. glXQueryDrawable = NULL; } setIsDirectRendering(bool(glXIsDirect(display(), ctx))); qDebug() << "Direct rendering:" << isDirectRendering() << endl; }
SceneOpenGL::SceneOpenGL(Workspace* ws) : Scene(ws) , m_resetModelViewProjectionMatrix(true) , init_ok(false) { initGLX(); // check for FBConfig support if (!hasGLExtension("GLX_SGIX_fbconfig") || !glXGetFBConfigAttrib || !glXGetFBConfigs || !glXGetVisualFromFBConfig || !glXCreatePixmap || !glXDestroyPixmap || !glXCreateWindow || !glXDestroyWindow) { kError(1212) << "GLX_SGIX_fbconfig or required GLX functions missing"; return; // error } if (!selectMode()) return; // error if (!initBuffer()) // create destination buffer return; // error if (!initRenderingContext()) return; // error // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(); glPlatform->printResults(); initGL(); if (glPlatform->isSoftwareEmulation()) { kError(1212) << "OpenGL Software Rasterizer detected. Falling back to XRender."; QTimer::singleShot(0, Workspace::self(), SLOT(fallbackToXRenderCompositing())); return; } if (!hasGLExtension("GL_ARB_texture_non_power_of_two") && !hasGLExtension("GL_ARB_texture_rectangle")) { kError(1212) << "GL_ARB_texture_non_power_of_two and GL_ARB_texture_rectangle missing"; return; // error } if (glPlatform->isMesaDriver() && glPlatform->mesaVersion() < kVersionNumber(7, 10)) { kError(1212) << "KWin requires at least Mesa 7.10 for OpenGL compositing."; return; } if (db) glDrawBuffer(GL_BACK); // Check whether certain features are supported has_waitSync = false; if (options->isGlVSync()) { if (glXGetVideoSync && glXSwapInterval && glXIsDirect(display(), ctxbuffer)) { unsigned int sync; if (glXGetVideoSync(&sync) == 0) { if (glXWaitVideoSync(1, 0, &sync) == 0) { // NOTICE at this time we should actually check whether we can successfully // deactivate the swapInterval "glXSwapInterval(0) == 0" // (because we don't actually want it active unless we explicitly run a glXSwapBuffers) // However mesa/dri will return a range error (6) because deactivating the // swapinterval (as of today) seems completely unsupported has_waitSync = true; glXSwapInterval(0); } else qWarning() << "NO VSYNC! glXWaitVideoSync(1,0,&uint) isn't 0 but" << glXWaitVideoSync(1, 0, &sync); } else qWarning() << "NO VSYNC! glXGetVideoSync(&uint) isn't 0 but" << glXGetVideoSync(&sync); } else qWarning() << "NO VSYNC! glXGetVideoSync, glXSwapInterval, glXIsDirect" << bool(glXGetVideoSync) << bool(glXSwapInterval) << glXIsDirect(display(), ctxbuffer); } debug = qstrcmp(qgetenv("KWIN_GL_DEBUG"), "1") == 0; // scene shader setup if (GLPlatform::instance()->supports(GLSL)) { if (!ShaderManager::instance()->isValid()) { kDebug(1212) << "No Scene Shaders available"; } else { // push one shader on the stack so that one is always bound // consistency with GLES ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); } } // OpenGL scene setup setupModelViewProjectionMatrix(); if (checkGLError("Init")) { kError(1212) << "OpenGL compositing setup failed"; return; // error } // set strict binding if (options->isGlStrictBindingFollowsDriver()) { options->setGlStrictBinding(!glPlatform->supports(LooseBinding)); } kDebug(1212) << "DB:" << db << ", Direct:" << bool(glXIsDirect(display(), ctxbuffer)) << endl; init_ok = true; }