From 57c27c2e0b00229a339712f123bc8bc4eac2f67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 5 Oct 2012 18:00:49 +0200 Subject: [PATCH] GLPlatform can recommend the compositor to use During detecting the OpenGL capabilities also a recommended compositor can be set. This recommendation is honoured by the OpenGL based compositors. That is the SceneOpenGL2 requires a recommendation for at least OpenGL2 and the SceneOpenGL1 requires at least a recommendation for OpenGL1. If the driver recommends XRender compositing the SceneOpenGL performs the existing fallback to XRender. With this recommendation the hacks in the Scene are removed, e.g. it is no longer checked whether the driver is software emulation as that is provided through the recommendation. To overrule the recommendation the environment variable KWIN_COMPOSE is extended by the values O1 and O2 to enforce either OpenGL 1 or OpenGL 2. This overwrites all other checks. As a side-effect this allows now to run KWin on the llvmpipe: LIBGL_ALWAYS_SOFTWARE=1 KWIN_COMPOSE=O2 kwin --replace & But not that I would recommend to use it :-) REVIEW: 106741 --- libkwineffects/kwinglplatform.cpp | 48 +++++++++++++++++++++++++++++-- libkwineffects/kwinglplatform.h | 7 +++++ scene_opengl.cpp | 44 +++++++++++++++++++++------- 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/libkwineffects/kwinglplatform.cpp b/libkwineffects/kwinglplatform.cpp index 823bade955..35d7ff53ee 100644 --- a/libkwineffects/kwinglplatform.cpp +++ b/libkwineffects/kwinglplatform.cpp @@ -502,6 +502,7 @@ QString GLPlatform::chipClassToString(ChipClass chipClass) GLPlatform::GLPlatform() : m_driver(Driver_Unknown), m_chipClass(UnknownChipClass), + m_recommendedCompositor(XRenderCompositing), m_mesaVersion(0), m_galliumVersion(0), m_looseBinding(false), @@ -753,6 +754,16 @@ void GLPlatform::detect(OpenGLPlatformInterface platformInterface) m_limitedGLSL = m_supportsGLSL; } + if (m_chipClass < R300) { + // fallback to XRender for R100 and R200 + m_recommendedCompositor = XRenderCompositing; + } else if (m_chipClass < R600) { + // OpenGL 1 due to NPOT limitations not supported by KWin's shaders + m_recommendedCompositor = OpenGL1Compositing; + } else { + m_recommendedCompositor = OpenGL2Compositing; + } + if (driver() == Driver_R600G || (driver() == Driver_R600C && m_renderer.contains("DRI2"))) { m_looseBinding = true; @@ -766,6 +777,14 @@ void GLPlatform::detect(OpenGLPlatformInterface platformInterface) if (m_driver == Driver_NVidia) m_looseBinding = true; + if (m_chipClass < NV20) { + m_recommendedCompositor = XRenderCompositing; + } else if (m_chipClass < NV40) { + m_recommendedCompositor = OpenGL1Compositing; + } else { + m_recommendedCompositor = OpenGL2Compositing; + } + m_limitedNPOT = m_textureNPOT && m_chipClass < NV40; m_limitedGLSL = m_supportsGLSL && m_chipClass < G80; } @@ -775,6 +794,12 @@ void GLPlatform::detect(OpenGLPlatformInterface platformInterface) m_supportsGLSL = false; m_limitedGLSL = m_supportsGLSL && m_chipClass < I965; + + if (m_chipClass < I965) { + m_recommendedCompositor = OpenGL1Compositing; + } else { + m_recommendedCompositor = OpenGL2Compositing; + } } if (isMesaDriver() && platformInterface == EglPlatformInterface) { @@ -789,8 +814,22 @@ void GLPlatform::detect(OpenGLPlatformInterface platformInterface) m_looseBinding = false; if (isSoftwareEmulation()) { - // Software emulation does not provide GLSL - m_limitedGLSL = m_supportsGLSL = false; + // we recommend XRender + m_recommendedCompositor = XRenderCompositing; + if (m_driver < Driver_Llvmpipe) { + // Software emulation does not provide GLSL + m_limitedGLSL = m_supportsGLSL = false; + } else { + // llvmpipe does support GLSL + 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()) { @@ -990,5 +1029,10 @@ bool GLPlatform::isVirtualMachine() const return m_virtualMachine; } +CompositingType GLPlatform::recommendedCompositor() const +{ + return m_recommendedCompositor; +} + } // namespace KWin diff --git a/libkwineffects/kwinglplatform.h b/libkwineffects/kwinglplatform.h index 79bf46d19f..249ecdb55e 100644 --- a/libkwineffects/kwinglplatform.h +++ b/libkwineffects/kwinglplatform.h @@ -296,6 +296,12 @@ public: **/ bool isLooseBinding() const; + /** + * @returns The CompositingType recommended by the driver. + * @since 4.10 + **/ + CompositingType recommendedCompositor() const; + /** * @returns a human readable form of the @p version. * @since 4.9 @@ -333,6 +339,7 @@ private: QSet m_extensions; Driver m_driver; ChipClass m_chipClass; + CompositingType m_recommendedCompositor; qint64 m_glVersion; qint64 m_glslVersion; qint64 m_mesaVersion; diff --git a/scene_opengl.cpp b/scene_opengl.cpp index de7abd8160..f2cf03fe13 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -80,6 +80,7 @@ Sources and other compositing managers: #include "utils.h" #include "client.h" +#include "composite.h" #include "deleted.h" #include "effects.h" #include "overlaywindow.h" @@ -150,11 +151,6 @@ SceneOpenGL::SceneOpenGL(Workspace* ws, OpenGLBackend *backend) // perform Scene specific checks GLPlatform *glPlatform = GLPlatform::instance(); - if (glPlatform->isSoftwareEmulation()) { - kError(1212) << "OpenGL Software Rasterizer detected. Falling back to XRender."; - QTimer::singleShot(0, Workspace::self(), SLOT(fallbackToXRenderCompositing())); - return; - } #ifndef KWIN_HAVE_OPENGLES if (!hasGLExtension("GL_ARB_texture_non_power_of_two") && !hasGLExtension("GL_ARB_texture_rectangle")) { @@ -256,6 +252,12 @@ SceneOpenGL *SceneOpenGL::createScene() } #endif if (!scene) { + if (GLPlatform::instance()->recommendedCompositor() == XRenderCompositing) { + kError(1212) << "OpenGL driver recommends XRender based compositing. Falling back to XRender."; + kError(1212) << "To overwrite the detection use the environment variable KWIN_COMPOSE"; + kError(1212) << "For more information see http://community.kde.org/KWin/Environment_Variables#KWIN_COMPOSE"; + QTimer::singleShot(0, Compositor::self(), SLOT(fallbackToXRenderCompositing())); + } delete backend; } @@ -439,14 +441,23 @@ void SceneOpenGL::screenGeometryChanged(const QSize &size) //**************************************** bool SceneOpenGL2::supported(OpenGLBackend *backend) { + const QByteArray forceEnv = qgetenv("KWIN_COMPOSE"); + if (!forceEnv.isEmpty()) { + if (qstrcmp(forceEnv, "O2") == 0) { + kDebug(1212) << "OpenGL 2 compositing enforced by environment variable"; + return true; + } else { + // OpenGL 2 disabled by environment variable + return false; + } + } if (!backend->isDirectRendering()) { return false; } -#ifdef KWIN_HAVE_OPENGL_1 - if (!GLPlatform::instance()->supports(GLSL) || GLPlatform::instance()->supports(LimitedNPOT)) { + if (GLPlatform::instance()->recommendedCompositor() < OpenGL2Compositing) { + kDebug(1212) << "Driver does not recommend OpenGL 2 compositing"; return false; } -#endif if (options->isGlLegacy()) { kDebug(1212) << "OpenGL 2 disabled by config option"; return false; @@ -510,8 +521,21 @@ SceneOpenGL::Window *SceneOpenGL2::createWindow(Toplevel *t) #ifdef KWIN_HAVE_OPENGL_1 bool SceneOpenGL1::supported(OpenGLBackend *backend) { - // any OpenGL context will do - return !backend->isFailed(); + const QByteArray forceEnv = qgetenv("KWIN_COMPOSE"); + if (!forceEnv.isEmpty()) { + if (qstrcmp(forceEnv, "O1") == 0) { + kDebug(1212) << "OpenGL 1 compositing enforced by environment variable"; + return true; + } else { + // OpenGL 1 disabled by environment variable + return false; + } + } + if (GLPlatform::instance()->recommendedCompositor() < OpenGL1Compositing) { + kDebug(1212) << "Driver does not recommend OpenGL 1 compositing"; + return false; + } + return true; } SceneOpenGL1::SceneOpenGL1(OpenGLBackend *backend)