Check max viewport and texture dimensions

REVIEW: 106917
This commit is contained in:
Thomas Lübking 2012-10-16 22:41:21 +02:00
parent c8e2b61f48
commit 36378925e7
5 changed files with 197 additions and 4 deletions

View file

@ -0,0 +1,46 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2012 Thomas Lübking <thomas.luebking@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef MAIN_ADAPTOR_H
#define MAIN_ADAPTOR_H
#include <QtDBus/QDBusAbstractAdaptor>
#include "main.h"
namespace KWin
{
class MainAdaptor : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kwinCompositingDialog")
private:
KWinCompositingConfig *m_config;
public:
MainAdaptor(KWinCompositingConfig *config) : QDBusAbstractAdaptor(config), m_config(config) { }
public slots:
Q_NOREPLY void warn(QString message, QString details, QString dontAgainKey) {
m_config->warn(message, details, dontAgainKey);
}
};
}
#endif

View file

@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "main.h"
#include "dbus.h"
#include "kwin_interface.h"
#include "kwinglobals.h"
@ -76,13 +77,17 @@ ConfirmDialog::ConfirmDialog() :
}
KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &)
KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList &args)
: KCModule(KWinCompositingConfigFactory::componentData(), parent)
, mKWinConfig(KSharedConfig::openConfig("kwinrc"))
, m_showConfirmDialog(false)
, m_showDetailedErrors(new QAction(i18nc("Action to open a dialog showing detailed information why an effect could not be loaded",
"Details"), this))
, m_dontShowAgain(new QAction(i18nc("Prevent warning from bein displayed again", "Don't show again!"), this))
{
QDBusConnection::sessionBus().registerService("org.kde.kwinCompositingDialog");
QDBusConnection::sessionBus().registerObject("/CompositorSettings", this);
new MainAdaptor(this);
KGlobal::locale()->insertCatalog("kwin_effects");
ui.setupUi(this);
layout()->setMargin(0);
@ -90,9 +95,34 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
ui.tabWidget->setCurrentIndex(0);
ui.statusTitleWidget->hide();
ui.rearmGlSupport->hide();
ui.messageBox->setVisible(false);
ui.messageBox->addAction(m_showDetailedErrors);
ui.messageBox->setMessageType(KMessageWidget::Warning);
ui.messageBox->addAction(m_dontShowAgain);
foreach (QWidget *w, m_dontShowAgain->associatedWidgets())
w->setVisible(false);
ui.messageBox->addAction(m_showDetailedErrors);
bool showMessage = false;
QString message, details, dontAgainKey;
if (args.count() > 1) {
for (int i = 0; i < args.count() - 1; ++i) {
if (args.at(i).toString() == "warn") {
showMessage = true;
message = QString::fromLocal8Bit(QByteArray::fromBase64(args.at(i+1).toByteArray()));
} else if (args.at(i).toString() == "details") {
showMessage = true;
details = QString::fromLocal8Bit(QByteArray::fromBase64(args.at(i+1).toByteArray()));
} else if (args.at(i).toString() == "dontagain") {
showMessage = true;
dontAgainKey = args.at(i+1).toString();
}
}
}
if (showMessage) {
ui.messageBox->setVisible(showMessage); // first show, animation is broken on init
warn(message, details, dontAgainKey);
} else
ui.messageBox->setVisible(false);
ui.ghns->setIcon(KIcon("get-hot-new-stuff"));
// For future use
@ -133,6 +163,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList
connect(ui.glShaders, SIGNAL(toggled(bool)), this, SLOT(changed()));
connect(ui.glColorCorrection, SIGNAL(toggled(bool)), this, SLOT(changed()));
connect(m_showDetailedErrors, SIGNAL(triggered(bool)), SLOT(showDetailedEffectLoadingInformation()));
connect(m_dontShowAgain, SIGNAL(triggered(bool)), SLOT(blockFutureWarnings()));
connect(ui.ghns, SIGNAL(clicked(bool)), SLOT(slotGHNS()));
// Open the temporary config file
@ -615,10 +646,15 @@ void KWinCompositingConfig::checkLoadedEffects()
}
if (!disabledEffects.isEmpty()) {
m_showDetailedErrors->setData(disabledEffects);
foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
w->setVisible(true);
ui.messageBox->setText(i18ncp("Error Message shown when a desktop effect could not be loaded",
"One desktop effect could not be loaded.",
"%1 desktop effects could not be loaded.", disabledEffects.count()));
ui.messageBox->animatedShow();
} else {
foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
w->setVisible(false);
}
}
}
@ -653,7 +689,9 @@ void KWinCompositingConfig::showDetailedEffectLoadingInformation()
label->setOpenExternalLinks(true);
vboxLayout->addWidget(titleWidget);
vboxLayout->addWidget(label);
if (compositingType != "none") {
if (!m_externErrorDetails.isNull()) {
label->setText(m_externErrorDetails);
} else if (compositingType != "none") {
QString text;
if (disabledEffects.count() > 1) {
text = "<ul>";
@ -716,6 +754,31 @@ void KWinCompositingConfig::showDetailedEffectLoadingInformation()
dialog->show();
}
void KWinCompositingConfig::warn(QString message, QString details, QString dontAgainKey)
{
ui.messageBox->setText(message);
m_dontShowAgain->setData(dontAgainKey);
foreach (QWidget *w, m_dontShowAgain->associatedWidgets())
w->setVisible(!dontAgainKey.isEmpty());
m_externErrorDetails = details.isNull() ? "" : details;
foreach (QWidget *w, m_showDetailedErrors->associatedWidgets())
w->setVisible(!m_externErrorDetails.isEmpty());
ui.messageBox->animatedShow();
}
void KWinCompositingConfig::blockFutureWarnings() {
QString key;
if (QAction *act = qobject_cast<QAction*>(sender()))
key = act->data().toString();
if (key.isEmpty())
return;
QStringList l = key.split(':', QString::SkipEmptyParts);
KConfig cfg(l.count() > 1 ? l.at(0) : "kwin_dialogsrc");
KConfigGroup(&cfg, "Notification Messages").writeEntry(l.last(), false);
cfg.sync();
ui.messageBox->animatedHide();
}
void KWinCompositingConfig::configChanged(bool reinitCompositing)
{
// Send signal to kwin
@ -779,4 +842,5 @@ void KWinCompositingConfig::slotGHNS()
} // namespace
#include "dbus.moc"
#include "main.moc"

View file

@ -74,6 +74,8 @@ public slots:
void configChanged(bool reinitCompositing);
void initEffectSelector();
void warn(QString message, QString details, QString dontAgainKey);
private slots:
void confirmReInit() { showConfirmDialog(true); }
void rearmGlSupport();
@ -82,6 +84,7 @@ private slots:
void toggleEffectShortcutChanged(const QKeySequence &seq);
void updateStatusUI(bool compositingIsPossible);
void showDetailedEffectLoadingInformation();
void blockFutureWarnings();
void slotGHNS();
private:
@ -97,6 +100,8 @@ private:
KActionCollection* m_actionCollection;
QString originalGraphicsSystem;
QAction *m_showDetailedErrors;
QAction *m_dontShowAgain;
QString m_externErrorDetails;
};
} // namespace

View file

@ -52,11 +52,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <X11/extensions/Xcomposite.h>
#include <qpainter.h>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusInterface>
#include <QDesktopWidget>
#include <QStringList>
#include <QVector2D>
#include <QVector4D>
#include <QMatrix4x4>
#include <KLocale>
#include <KProcess>
namespace KWin
{
@ -107,6 +114,8 @@ SceneOpenGL::SceneOpenGL(Workspace* ws, OpenGLBackend *backend)
init_ok = false;
return;
}
if (!viewportLimitsMatched(QSize(displayWidth(), displayHeight())))
return;
// perform Scene specific checks
GLPlatform *glPlatform = GLPlatform::instance();
@ -389,8 +398,75 @@ SceneOpenGL::Texture *SceneOpenGL::createTexture(const QPixmap &pix, GLenum targ
return new Texture(m_backend, pix, target);
}
bool SceneOpenGL::viewportLimitsMatched(const QSize &size) const {
GLint limit[2];
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, limit);
if (limit[0] < size.width() || limit[1] < size.height()) {
QMetaObject::invokeMethod(Compositor::self(), "suspend",
Qt::QueuedConnection, Q_ARG(Compositor::SuspendReason, Compositor::AllReasonSuspend));
const QString message = i18n("<h1>OpenGL desktop effects not possible</h1>"
"Your system cannot perform OpenGL Desktop Effects at the "
"current resolution<br><br>"
"You can try to select the XRender backend , but it "
"might be very slow for this resolution as well.<br>"
"Alternatively, lower the combined resolution of all screens "
"to %1x%2 ", limit[0], limit[1]);
const QString details = i18n("The demanded resolution exceeds the GL_MAX_VIEWPORT_DIMS "
"limitation of your GPU and is therefore not compatible "
"with the OpenGL compositor.<br>"
"XRender does not know such limitation, but the performance "
"will usually be impacted by the hardware limitations that"
"restrict the OpenGL viewport size.");
const int oldTimeout = QDBusConnection::sessionBus().interface()->timeout();
QDBusConnection::sessionBus().interface()->setTimeout(500);
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwinCompositingDialog").value()) {
QDBusInterface dialog( "org.kde.kwinCompositingDialog", "/CompositorSettings", "org.kde.kwinCompositingDialog" );
dialog.asyncCall("warn", message, details, "");
} else {
const QString args = "warn " + message.toLocal8Bit().toBase64() + " details " + details.toLocal8Bit().toBase64();
KProcess::startDetached("kcmshell4", QStringList() << "kwincompositing" << "--args" << args);
}
QDBusConnection::sessionBus().interface()->setTimeout(oldTimeout);
return false;
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, limit);
if (limit[0] < size.width() || limit[0] < size.height()) {
KConfig cfg("kwin_dialogsrc");
if (!KConfigGroup(&cfg, "Notification Messages").readEntry("max_tex_warning", true))
return true;
const QString message = i18n("<h1>OpenGL desktop effects might be unusable</h1>"
"OpenGL Desktop Effects at the current resolution are supported "
"but might be exceptionally slow.<br>"
"Also large windows will turn entirely black.<br><br>"
"Consider to suspend compositing, switch to the XRender backend "
"or lower the resolution to %1x%1." , limit[0]);
const QString details = i18n("The demanded resolution exceeds the GL_MAX_TEXTURE_SIZE "
"limitation of your GPU, thus windows of that size cannot be "
"assigned to textures and will be entirely black.<br>"
"Also this limit will often be a performance level barrier despite "
"below GL_MAX_VIEWPORT_DIMS, because the driver might fall back to "
"software rendering in this case.");
const int oldTimeout = QDBusConnection::sessionBus().interface()->timeout();
QDBusConnection::sessionBus().interface()->setTimeout(500);
if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kwinCompositingDialog").value()) {
QDBusInterface dialog( "org.kde.kwinCompositingDialog", "/CompositorSettings", "org.kde.kwinCompositingDialog" );
dialog.asyncCall("warn", message, details, "kwin_dialogsrc:max_tex_warning");
} else {
const QString args = "warn " + message.toLocal8Bit().toBase64() + " details " +
details.toLocal8Bit().toBase64() + " dontagain kwin_dialogsrc:max_tex_warning";
KProcess::startDetached("kcmshell4", QStringList() << "kwincompositing" << "--args" << args);
}
QDBusConnection::sessionBus().interface()->setTimeout(oldTimeout);
}
return true;
}
void SceneOpenGL::screenGeometryChanged(const QSize &size)
{
if (!viewportLimitsMatched(size))
return;
Scene::screenGeometryChanged(size);
glViewport(0,0, size.width(), size.height());
m_backend->screenGeometryChanged(size);

View file

@ -78,6 +78,8 @@ public Q_SLOTS:
virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted);
protected:
bool init_ok;
private:
bool viewportLimitsMatched(const QSize &size) const;
private:
QHash< Toplevel*, Window* > windows;
bool debug;