void LanczosFilter::init() { if (m_inited) return; m_inited = true; const bool force = (qstrcmp(qgetenv("KWIN_FORCE_LANCZOS"), "1") == 0); if (force) { kWarning(1212) << "Lanczos Filter forced on by environment variable"; } if (!force && options->glSmoothScale() != 2) return; // disabled by config // The lanczos filter is reported to be broken with the Intel driver and Mesa 7.10 GLPlatform *gl = GLPlatform::instance(); if (!force && gl->driver() == Driver_Intel && gl->mesaVersion() >= kVersionNumber(7, 10) && gl->chipClass() < SandyBridge) return; // With fglrx the ARB Shader crashes KWin (see Bug #270818 and #286795) and GLSL Shaders are not functional if (!force && gl->driver() == Driver_Catalyst) { return; } m_shader = new LanczosShader(this); if (!m_shader->init()) { delete m_shader; m_shader = 0; } }
CoverSwitchEffect::CoverSwitchEffect() : mActivated(0) , angle(60.0) , animation(false) , start(false) , stop(false) , stopRequested(false) , startRequested(false) , zPosition(900.0) , scaleFactor(0.0) , direction(Left) , selected_window(0) , captionFrame(NULL) , primaryTabBox(false) , secondaryTabBox(false) { reconfigure(ReconfigureAll); // Caption frame captionFont.setBold(true); captionFont.setPointSize(captionFont.pointSize() * 2); if (effects->compositingType() == OpenGL2Compositing) { QString shadersDir = QStringLiteral("kwin/shaders/1.10/"); #ifdef KWIN_HAVE_OPENGLES const qint64 coreVersionNumber = kVersionNumber(3, 0); #else const qint64 coreVersionNumber = kVersionNumber(1, 40); #endif if (GLPlatform::instance()->glslVersion() >= coreVersionNumber) shadersDir = QStringLiteral("kwin/shaders/1.40/"); const QString fragmentshader = QStandardPaths::locate(QStandardPaths::GenericDataLocation, shadersDir + QStringLiteral("coverswitch-reflection.glsl")); m_reflectionShader = ShaderManager::instance()->loadFragmentShader(ShaderManager::GenericShader, fragmentshader); } else { m_reflectionShader = NULL; } connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*))); connect(effects, SIGNAL(tabBoxAdded(int)), this, SLOT(slotTabBoxAdded(int))); connect(effects, SIGNAL(tabBoxClosed()), this, SLOT(slotTabBoxClosed())); connect(effects, SIGNAL(tabBoxUpdated()), this, SLOT(slotTabBoxUpdated())); connect(effects, SIGNAL(tabBoxKeyEvent(QKeyEvent*)), this, SLOT(slotTabBoxKeyEvent(QKeyEvent*))); }
static qint64 getXServerVersion() { qint64 major, minor, patch; Display *dpy = display(); if (dpy && strstr(ServerVendor(dpy), "X.Org")) { const int release = VendorRelease(dpy); major = (release / 10000000); minor = (release / 100000) % 100; patch = (release / 1000) % 100; } else { major = 0; minor = 0; patch = 0; } return kVersionNumber(major, minor, patch); }
void GLPlatform::detect(OpenGLPlatformInterface platformInterface) { m_platformInterface = platformInterface; m_vendor = (const char*)glGetString(GL_VENDOR); m_renderer = (const char*)glGetString(GL_RENDERER); m_version = (const char*)glGetString(GL_VERSION); // Parse the OpenGL version const QList<QByteArray> versionTokens = m_version.split(' '); if (versionTokens.count() > 0) { const QByteArray version = QByteArray(m_version); m_glVersion = parseVersionString(version); if (platformInterface == EglPlatformInterface) { // only EGL can have OpenGLES, GLX is OpenGL only if (version.startsWith("OpenGL ES")) { // from GLES 2: "Returns a version or release number of the form OpenGL<space>ES<space><version number><space><vendor-specific information>." // from GLES 3: "Returns a version or release number." and "The version number uses one of these forms: major_number.minor_number major_number.minor_number.release_number" m_gles = true; } } } if (!isGLES() && m_glVersion >= kVersionNumber(3, 0)) { int count; glGetIntegerv(GL_NUM_EXTENSIONS, &count); for (int i = 0; i < count; i++) { const char *name = (const char *) glGetStringi(GL_EXTENSIONS, i); m_extensions.insert(name); } } else { const QByteArray extensions = (const char *) glGetString(GL_EXTENSIONS); m_extensions = QSet<QByteArray>::fromList(extensions.split(' ')); } // Parse the Mesa version const int mesaIndex = versionTokens.indexOf("Mesa"); if (mesaIndex != -1) { const QByteArray version = versionTokens.at(mesaIndex + 1); m_mesaVersion = parseVersionString(version); } if (platformInterface == EglPlatformInterface) { if (isGLES()) { m_supportsGLSL = true; m_textureNPOT = true; } else { m_supportsGLSL = m_extensions.contains("GL_ARB_shader_objects") && m_extensions.contains("GL_ARB_fragment_shader") && m_extensions.contains("GL_ARB_vertex_shader"); m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); } } else if (platformInterface == GlxPlatformInterface) { m_supportsGLSL = m_extensions.contains("GL_ARB_shader_objects") && m_extensions.contains("GL_ARB_fragment_shader") && m_extensions.contains("GL_ARB_vertex_shader"); m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); } m_serverVersion = getXServerVersion(); m_kernelVersion = getKernelVersion(); m_glslVersion = 0; m_glsl_version.clear(); if (m_supportsGLSL) { // Parse the GLSL version m_glsl_version = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); m_glslVersion = parseVersionString(m_glsl_version); } m_chipset = QByteArrayLiteral("Unknown"); m_preferBufferSubData = false; // Mesa classic drivers // ==================================================== // Radeon if (m_renderer.startsWith("Mesa DRI R")) { // Sample renderer string: Mesa DRI R600 (RV740 94B3) 20090101 x86/MMX/SSE2 TCL DRI2 const QList<QByteArray> tokens = m_renderer.split(' '); const QByteArray chipClass = tokens.at(2); m_chipset = tokens.at(3).mid(1, -1); // Strip the leading '(' if (chipClass == "R100") // Vendor: Tungsten Graphics, Inc. m_driver = Driver_R100; else if (chipClass == "R200") // Vendor: Tungsten Graphics, Inc. m_driver = Driver_R200; else if (chipClass == "R300") // Vendor: DRI R300 Project m_driver = Driver_R300C; else if (chipClass == "R600") // Vendor: Advanced Micro Devices, Inc. m_driver = Driver_R600C; m_chipClass = detectRadeonClass(m_chipset); } // Intel else if (m_renderer.contains("Intel")) { // Vendor: Tungsten Graphics, Inc. // Sample renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100328 2010Q1 QByteArray chipset; if (m_renderer.startsWith("Intel(R) Integrated Graphics Device")) chipset = "IGD"; else chipset = m_renderer; m_driver = Driver_Intel; m_chipClass = detectIntelClass(chipset); } // Gallium drivers // ==================================================== else if (m_renderer.contains("Gallium")) { // Sample renderer string: Gallium 0.4 on AMD RV740 const QList<QByteArray> tokens = m_renderer.split(' '); m_galliumVersion = parseVersionString(tokens.at(1)); m_chipset = (tokens.at(3) == "AMD" || tokens.at(3) == "ATI") ? tokens.at(4) : tokens.at(3); // R300G if (m_vendor == QByteArrayLiteral("X.Org R300 Project")) { m_chipClass = detectRadeonClass(m_chipset); m_driver = Driver_R300G; } // R600G else if (m_vendor == "X.Org" && (m_renderer.contains("R6") || m_renderer.contains("R7") || m_renderer.contains("RV6") || m_renderer.contains("RV7") || m_renderer.contains("RS780") || m_renderer.contains("RS880") || m_renderer.contains("CEDAR") || m_renderer.contains("REDWOOD") || m_renderer.contains("JUNIPER") || m_renderer.contains("CYPRESS") || m_renderer.contains("HEMLOCK") || m_renderer.contains("PALM") || m_renderer.contains("EVERGREEN") || m_renderer.contains("SUMO") || m_renderer.contains("SUMO2") || m_renderer.contains("BARTS") || m_renderer.contains("TURKS") || m_renderer.contains("CAICOS") || m_renderer.contains("CAYMAN"))) { m_chipClass = detectRadeonClass(m_chipset); m_driver = Driver_R600G; } // Nouveau else if (m_vendor == "nouveau") { m_chipClass = detectNVidiaClass(m_chipset); m_driver = Driver_Nouveau; } // softpipe else if (m_vendor == "VMware, Inc." && m_chipset == "softpipe" ) { m_driver = Driver_Softpipe; } // llvmpipe else if (m_vendor == "VMware, Inc." && m_chipset == "llvmpipe") { m_driver = Driver_Llvmpipe; } // SVGA3D else if (m_vendor == "VMware, Inc." && m_chipset.contains("SVGA3D")) { m_driver = Driver_VMware; } } // Properietary drivers // ==================================================== else if (m_vendor == "ATI Technologies Inc.") { m_chipClass = detectRadeonClass(m_renderer); m_driver = Driver_Catalyst; if (versionTokens.count() > 1 && versionTokens.at(2)[0] == '(') m_driverVersion = parseVersionString(versionTokens.at(1)); else if (versionTokens.count() > 0) m_driverVersion = parseVersionString(versionTokens.at(0)); else m_driverVersion = 0; } else if (m_vendor == "NVIDIA Corporation") { m_chipClass = detectNVidiaClass(m_renderer); m_driver = Driver_NVidia; int index = versionTokens.indexOf("NVIDIA"); if (versionTokens.count() > index) m_driverVersion = parseVersionString(versionTokens.at(index + 1)); else m_driverVersion = 0; } else if (m_renderer == "Software Rasterizer") { m_driver = Driver_Swrast; } // Virtual Hardware // ==================================================== else if (m_vendor == "Humper" && m_renderer == "Chromium") { // Virtual Box m_driver = Driver_VirtualBox; const int index = versionTokens.indexOf("Chromium"); if (versionTokens.count() > index) m_driverVersion = parseVersionString(versionTokens.at(index + 1)); else m_driverVersion = 0; } // Driver/GPU specific features // ==================================================== if (isRadeon()) { // R200 technically has a programmable pipeline, but since it's SM 1.4, // it's too limited to to be of any practical value to us. if (m_chipClass < R300) m_supportsGLSL = false; m_limitedGLSL = false; m_limitedNPOT = false; if (m_chipClass < R600) { if (driver() == Driver_Catalyst) m_textureNPOT = m_limitedNPOT = false; // Software fallback else if (driver() == Driver_R300G) m_limitedNPOT = m_textureNPOT; m_limitedGLSL = m_supportsGLSL; } if (m_chipClass < R300) { // fallback to XRender for R100 and R200 m_recommendedCompositor = XRenderCompositing; } else if (m_chipClass < R600) { // XRender due to NPOT limitations not supported by KWin's shaders m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } if (driver() == Driver_R600G || (driver() == Driver_R600C && m_renderer.contains("DRI2"))) { m_looseBinding = true; } } if (isNvidia()) { if (m_driver == Driver_NVidia && m_chipClass < NV40) m_supportsGLSL = false; // High likelihood of software emulation if (m_driver == Driver_NVidia) { m_looseBinding = true; m_preferBufferSubData = true; } if (m_chipClass < NV40) { m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } m_limitedNPOT = m_textureNPOT && m_chipClass < NV40; m_limitedGLSL = m_supportsGLSL && m_chipClass < G80; } if (isIntel()) { if (m_chipClass < I915) m_supportsGLSL = false; m_limitedGLSL = m_supportsGLSL && m_chipClass < I965; // see https://bugs.freedesktop.org/show_bug.cgi?id=80349#c1 m_looseBinding = false; if (m_chipClass < I915) { m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } } if (isMesaDriver() && platformInterface == EglPlatformInterface) { // According to the reference implementation in // mesa/demos/src/egl/opengles1/texture_from_pixmap // the mesa egl implementation does not require a strict binding (so far). m_looseBinding = true; } if (isSoftwareEmulation()) { if (m_driver < Driver_Llvmpipe) { // we recommend XRender m_recommendedCompositor = XRenderCompositing; // Software emulation does not provide GLSL m_limitedGLSL = m_supportsGLSL = false; } else { // llvmpipe does support GLSL m_recommendedCompositor = OpenGL2Compositing; m_limitedGLSL = false; m_supportsGLSL = true; } } if (m_chipClass == UnknownChipClass && m_driver == Driver_Unknown) { // we don't know the hardware. Let's be optimistic and assume OpenGL compatible hardware m_recommendedCompositor = OpenGL2Compositing; m_supportsGLSL = true; } if (isVirtualBox()) { m_virtualMachine = true; m_recommendedCompositor = OpenGL2Compositing; } if (isVMware()) { m_virtualMachine = true; m_recommendedCompositor = OpenGL2Compositing; } // and force back to shader supported on gles, we wouldn't have got a context if not supported if (isGLES()) { m_supportsGLSL = true; m_limitedGLSL = false; } }
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; }