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
This commit is contained in:
Martin Gräßlin 2012-10-05 18:00:49 +02:00
parent 99db844912
commit 57c27c2e0b
3 changed files with 87 additions and 12 deletions

View file

@ -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

View file

@ -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<QByteArray> m_extensions;
Driver m_driver;
ChipClass m_chipClass;
CompositingType m_recommendedCompositor;
qint64 m_glVersion;
qint64 m_glslVersion;
qint64 m_mesaVersion;

View file

@ -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)