Check max viewport and texture dimensions
REVIEW: 106917
This commit is contained in:
parent
c8e2b61f48
commit
36378925e7
5 changed files with 197 additions and 4 deletions
46
kcmkwin/kwincompositing/dbus.h
Normal file
46
kcmkwin/kwincompositing/dbus.h
Normal 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
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue