From a417888b0e0e9a6ef1ff346ceb23dcd04c539fd1 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Wed, 11 Jul 2012 19:43:54 +0300 Subject: [PATCH 01/20] Implement color correction support The implementation consists of a class in libkwineffects. There are some slight modifications in the compositor. Regions for different outputs are drawn at different times. Currently only per output color correction is implemented. However, the grounds are prepared for implementing per window color correction easily. The ColorCorrection class needs to communicate via D-Bus with a KDED module, KolorServer, which is a part of KolorManager. The only visible part for the user consists of a check box in the advanced tab for the compositing KCM. The actual correction is done by injecting a piece of code in the fragment shader, code that does a 3D lookup into a special color lookup texture. The data for these textures is obtained from KolorServer. All D-Bus calls are async. --- composite.cpp | 7 + kcmkwin/kwincompositing/main.cpp | 5 +- kcmkwin/kwincompositing/main.ui | 47 +- libkwineffects/CMakeLists.txt | 1 + libkwineffects/kwineffects.cpp | 13 + libkwineffects/kwineffects.h | 12 + libkwineffects/kwinglcolorcorrection.cpp | 711 +++++++++++++++++++++++ libkwineffects/kwinglcolorcorrection.h | 143 +++++ libkwineffects/kwinglcolorcorrection_p.h | 168 ++++++ libkwineffects/kwinglutils.cpp | 19 +- libkwineffects/kwinglutils.h | 1 + options.cpp | 11 + options.h | 10 + scene.cpp | 13 +- scene.h | 2 +- scene_opengl.cpp | 102 +++- scene_opengl.h | 18 +- workspace.cpp | 1 + 18 files changed, 1221 insertions(+), 63 deletions(-) create mode 100644 libkwineffects/kwinglcolorcorrection.cpp create mode 100644 libkwineffects/kwinglcolorcorrection.h create mode 100644 libkwineffects/kwinglcolorcorrection_p.h diff --git a/composite.cpp b/composite.cpp index 12bb75a8df..8fbbd5356e 100644 --- a/composite.cpp +++ b/composite.cpp @@ -55,6 +55,8 @@ along with this program. If not, see . #include "compositingprefs.h" #include "notifications.h" +#include + #include #include @@ -140,6 +142,10 @@ void Workspace::slotCompositingOptionsInitialized() } #endif + kDebug(1212) << "Color correction:" << options->isGlColorCorrection(); + ColorCorrection::instance()->setEnabled(options->isGlColorCorrection()); + connect(ColorCorrection::instance(), SIGNAL(changed()), this, SLOT(addRepaintFull())); + scene = new SceneOpenGL(this); // TODO: Add 30 second delay to protect against screen freezes as well @@ -204,6 +210,7 @@ void Workspace::finishCompositing() if (scene == NULL) return; m_finishingCompositing = true; + ColorCorrection::cleanup(); delete cm_selection; foreach (Client * c, clients) scene->windowClosed(c, NULL); diff --git a/kcmkwin/kwincompositing/main.cpp b/kcmkwin/kwincompositing/main.cpp index 7a89db49fa..b958ff6dc0 100644 --- a/kcmkwin/kwincompositing/main.cpp +++ b/kcmkwin/kwincompositing/main.cpp @@ -128,6 +128,7 @@ KWinCompositingConfig::KWinCompositingConfig(QWidget *parent, const QVariantList connect(ui.glVSync, SIGNAL(toggled(bool)), this, SLOT(changed())); 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())); // Open the temporary config file @@ -381,6 +382,7 @@ void KWinCompositingConfig::loadAdvancedTab() ui.glVSync->setChecked(config.readEntry("GLVSync", true)); ui.glShaders->setChecked(!config.readEntry("GLLegacy", false)); + ui.glColorCorrection->setChecked(config.readEntry("GLColorCorrection", false)); toogleSmoothScaleUi(ui.compositingType->currentIndex()); } @@ -514,7 +516,7 @@ bool KWinCompositingConfig::saveAdvancedTab() config.writeEntry("GLVSync", ui.glVSync->isChecked()); config.writeEntry("GLLegacy", !ui.glShaders->isChecked()); - + config.writeEntry("GLColorCorrection", ui.glColorCorrection->isChecked()); return advancedChanged; } @@ -752,6 +754,7 @@ void KWinCompositingConfig::defaults() ui.glScaleFilter->setCurrentIndex(2); ui.glVSync->setChecked(true); ui.glShaders->setChecked(true); + ui.glColorCorrection->setChecked(false); } QString KWinCompositingConfig::quickHelp() const diff --git a/kcmkwin/kwincompositing/main.ui b/kcmkwin/kwincompositing/main.ui index cff0f63b16..fcac221ed2 100644 --- a/kcmkwin/kwincompositing/main.ui +++ b/kcmkwin/kwincompositing/main.ui @@ -778,6 +778,17 @@ p, li { white-space: pre-wrap; } true + + + + If enabled all rendering will be performed with Shaders written in the OpenGL Shading Language. +On legacy hardware disabling Shaders can improve the performance. + + + Use OpenGL 2 Shaders + + + @@ -788,14 +799,16 @@ p, li { white-space: pre-wrap; } - - + + + + false + - If enabled all rendering will be performed with Shaders written in the OpenGL Shading Language. -On legacy hardware disabling Shaders can improve the performance. + <html><head/><body><p>Activates color correction if possible, using the Kolor-Manager. Requires OpenGL 2 Shaders to be enabled and <span style=" text-decoration: underline;">Kolor-Manager to be installed</span>. May fail silently.</p><p><span style=" font-weight:600;">Experimental.</span></p></body></html> - Use OpenGL 2 Shaders + Enable color correction (experimental) @@ -893,12 +906,28 @@ On legacy hardware disabling Shaders can improve the performance. setEnabled(bool) - 161 - 64 + 312 + 119 - 194 - 119 + 345 + 146 + + + + + glShaders + toggled(bool) + glColorCorrection + setEnabled(bool) + + + 204 + 315 + + + 204 + 358 diff --git a/libkwineffects/CMakeLists.txt b/libkwineffects/CMakeLists.txt index 14a2747d6e..97a072f016 100644 --- a/libkwineffects/CMakeLists.txt +++ b/libkwineffects/CMakeLists.txt @@ -29,6 +29,7 @@ set(kwin_GLUTILSLIB_SRCS kwingltexture.cpp kwinglutils_funcs.cpp kwinglplatform.cpp + kwinglcolorcorrection.cpp ) macro( KWIN4_ADD_GLUTILS_BACKEND name glinclude ) diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index bae85e79b5..1f82da7b33 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -211,6 +211,7 @@ public: qreal decorationOpacity; qreal saturation; qreal brightness; + qint32 screen; }; WindowPaintData::WindowPaintData(EffectWindow* w) @@ -223,6 +224,7 @@ WindowPaintData::WindowPaintData(EffectWindow* w) setDecorationOpacity(1.0); setSaturation(1.0); setBrightness(1.0); + setScreen(0); } WindowPaintData::WindowPaintData(const WindowPaintData &other) @@ -242,6 +244,7 @@ WindowPaintData::WindowPaintData(const WindowPaintData &other) setDecorationOpacity(other.decorationOpacity()); setSaturation(other.saturation()); setBrightness(other.brightness()); + setScreen(other.screen()); } WindowPaintData::~WindowPaintData() @@ -269,6 +272,11 @@ qreal WindowPaintData::brightness() const return d->brightness; } +qint32 WindowPaintData::screen() const +{ + return d->screen; +} + void WindowPaintData::setDecorationOpacity(qreal opacity) { d->decorationOpacity = opacity; @@ -289,6 +297,11 @@ void WindowPaintData::setBrightness(qreal brightness) d->brightness = brightness; } +void WindowPaintData::setScreen(qint32 screen) const +{ + d->screen = screen; +} + qreal WindowPaintData::multiplyDecorationOpacity(qreal factor) { d->decorationOpacity *= factor; diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index 2c2f7bf5ed..bd2e8f2897 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1937,6 +1937,18 @@ public: * @since 4.10 **/ qreal multiplyBrightness(qreal factor); + /** + * The screen number for which the painting should be done. + * This affects color correction (different screens may need different + * color correction lookup tables because they have different ICC profiles). + * @return screen for which painting should be done + */ + qint32 screen() const; + /** + * @param screen New screen number + * A value less than 0 will indicate that a default profile should be done. + */ + void setScreen(qint32 screen) const; WindowQuadList quads; /** * Shader to be used for rendering, if any. diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp new file mode 100644 index 0000000000..3c066fb4c7 --- /dev/null +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -0,0 +1,711 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2012 Casian Andrei + +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 . +*********************************************************************/ + +#include "kwinglcolorcorrection.h" +#include "kwinglcolorcorrection_p.h" + +#include "kwinglutils.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace KWin { + +/* + * Color lookup table + * + * The 3D lookup texture has 64 points in each dimension, using 16 bit integers. + * That means each active region will use 1.5MiB of texture memory. + */ +static const int LUT_GRID_POINTS = 64; +static const size_t CLUT_ELEMENT_SIZE = sizeof(quint16); +static const uint CLUT_ELEMENT_COUNT = LUT_GRID_POINTS * LUT_GRID_POINTS * LUT_GRID_POINTS * 3; +static const size_t CLUT_DATA_SIZE = CLUT_ELEMENT_COUNT * CLUT_ELEMENT_SIZE; + +inline static void buildDummyClut(Clut &c) +{ + c.resize(CLUT_ELEMENT_COUNT); + quint16 *p = c.data(); + + for (int ib = 0; ib < LUT_GRID_POINTS; ++ ib) { + quint16 b = (quint16) ((float) ib / (LUT_GRID_POINTS - 1) * 65535.0 + 0.5); + for (int ig = 0; ig < LUT_GRID_POINTS; ++ ig) { + quint16 g = (quint16) ((float) ig / (LUT_GRID_POINTS - 1) * 65535.0 + 0.5); + for (int ir = 0; ir < LUT_GRID_POINTS; ++ ir) { + quint16 r = (quint16) ((float) ir / (LUT_GRID_POINTS - 1) * 65535.0 + 0.5); + + *(p ++) = r; + *(p ++) = g; + *(p ++) = b; + } + } + } +} + + +/* + * Color Server Interface + */ + +ColorServerInterface::ColorServerInterface(const QString &service, + const QString &path, + const QDBusConnection &connection, + QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) + , m_versionInfoWatcher(0) + , m_outputClutsWatcher(0) + , m_regionClutsWatcher(0) + , m_versionInfoUpdated(false) + , m_outputClutsUpdated(false) + , m_regionClutsUpdated(false) + , m_versionInfo(0) + , m_signaledFail(false) +{ + qDBusRegisterMetaType< Clut >(); + qDBusRegisterMetaType< ClutList >(); + qDBusRegisterMetaType< RegionalClut >(); + qDBusRegisterMetaType< RegionalClutMap >(); + + connect(this, SIGNAL(outputClutsChanged()), this, SLOT(update())); + connect(this, SIGNAL(regionClutsChanged()), this, SLOT(update())); +} + +ColorServerInterface::~ColorServerInterface() +{ +} + +uint ColorServerInterface::versionInfo() const +{ + if (!m_versionInfoUpdated) + kWarning(1212) << "Version info not updated"; + return m_versionInfo; +} + +const ClutList& ColorServerInterface::outputCluts() const +{ + return m_outputCluts; +} + +const RegionalClutMap& ColorServerInterface::regionCluts() const +{ + return m_regionCluts; +} + +void ColorServerInterface::update() +{ + m_versionInfoUpdated = false; + m_outputClutsUpdated = false; + m_regionClutsUpdated = false; + delete m_versionInfoWatcher; + delete m_outputClutsWatcher; + delete m_regionClutsWatcher; + m_versionInfoWatcher = new QDBusPendingCallWatcher(getVersionInfo(), this); + m_outputClutsWatcher = new QDBusPendingCallWatcher(getOutputCluts(), this); + m_regionClutsWatcher = new QDBusPendingCallWatcher(getRegionCluts(), this); + connect(m_versionInfoWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(callFinishedSlot(QDBusPendingCallWatcher*))); + connect(m_outputClutsWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(callFinishedSlot(QDBusPendingCallWatcher*))); + connect(m_regionClutsWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(callFinishedSlot(QDBusPendingCallWatcher*))); + + m_signaledFail = false; +} + +QDBusPendingReply< uint > ColorServerInterface::getVersionInfo() +{ + return QDBusPendingReply< uint >(asyncCall("getVersionInfo")); +} + +QDBusPendingReply< ClutList > ColorServerInterface::getOutputCluts() +{ + return QDBusPendingReply< ClutList >(asyncCall("getOutputCluts")); +} + +QDBusPendingReply< RegionalClutMap > ColorServerInterface::getRegionCluts() +{ + return QDBusPendingReply< RegionalClutMap >(asyncCall("getRegionCluts")); +} + +void ColorServerInterface::callFinishedSlot(QDBusPendingCallWatcher *watcher) +{ + if (watcher == m_versionInfoWatcher) { + kDebug(1212) << "Version info call finished"; + QDBusPendingReply< uint > reply = *watcher; + if (reply.isError()) { + kWarning(1212) << reply.error(); + if (!m_signaledFail) + emit updateFailed(); + m_signaledFail = true; + return; + } else { + m_versionInfo = reply.value(); + m_versionInfoUpdated = true; + } + } + + if (watcher == m_outputClutsWatcher) { + kDebug(1212) << "Output cluts call finished"; + QDBusPendingReply< ClutList > reply = *watcher; + if (reply.isError()) { + kWarning(1212) << reply.error(); + if (!m_signaledFail) + emit updateFailed(); + m_signaledFail = true; + return; + } else { + m_outputCluts = reply.value(); + m_outputClutsUpdated = true; + } + } + + if (watcher == m_regionClutsWatcher) { + kDebug(1212) << "Region cluts call finished"; + QDBusPendingReply< RegionalClutMap > reply = *watcher; + if (reply.isError()) { + kWarning(1212) << reply.error(); + if (!m_signaledFail) + emit updateFailed(); + m_signaledFail = true; + return; + } else { + m_regionCluts = reply.value(); + m_regionClutsUpdated = true; + } + } + + if (m_versionInfoUpdated && + m_outputClutsUpdated && + m_regionClutsUpdated) { + kDebug(1212) << "Update succeeded"; + emit updateSucceeded(); + } +} + + +/* + * To be injected in the fragment shader sources + */ +static const char s_ccVars[] = + "uniform sampler3D u_ccLookupTexture;\n"; +static const char s_ccAlteration[] = + "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb * 63.0 / 64.0).rgb;\n"; + + +/* + * Color Correction + */ + +ColorCorrection *ColorCorrection::s_colorCorrection = NULL; + +ColorCorrection *ColorCorrection::instance() +{ + if (!s_colorCorrection) + s_colorCorrection = new ColorCorrection; + return s_colorCorrection; +} + +void ColorCorrection::cleanup() +{ + delete s_colorCorrection; + s_colorCorrection = NULL; +} + +ColorCorrection::ColorCorrection() + : QObject() + , d_ptr(new ColorCorrectionPrivate(this)) +{ + +} + +ColorCorrection::~ColorCorrection() +{ + setEnabled(false); +} + +ColorCorrectionPrivate::ColorCorrectionPrivate(ColorCorrection *parent) + : QObject(parent) + , m_enabled(false) + , m_hasError(false) + , m_ccTextureUnit(-1) + , m_dummyCCTexture(0) + , m_lastOutput(-1) + , q_ptr(parent) +{ + // We need a dummy color lookup table (sRGB profile to sRGB profile) + buildDummyClut(m_dummyClut); + + // Establish a D-Bus communication interface with KolorServer + m_csi = new ColorServerInterface( + "org.kde.kded", + "/modules/kolorserver", + QDBusConnection::sessionBus(), + this); + + m_outputCluts = &m_csi->outputCluts(); + m_regionCluts = &m_csi->regionCluts(); + + connect(m_csi, SIGNAL(updateSucceeded()), this, SLOT(colorServerUpdateSucceededSlot())); + connect(m_csi, SIGNAL(updateFailed()), this, SLOT(colorServerUpdateFailedSlot())); +} + +ColorCorrectionPrivate::~ColorCorrectionPrivate() +{ + +} + +void ColorCorrection::setEnabled(bool enabled) +{ + Q_D(ColorCorrection); + + if (enabled == d->m_enabled) + return; + + if (enabled && d->m_hasError) { + kError(1212) << "cannot enable color correction"; + return; + } + +#ifdef KWIN_HAVE_OPENGLES + if (enabled) { + kWarning(1212) << "color correction is not supported with OpenGL ES at the moment."; + return; + } +#else + if (enabled) { + // Update all profiles and regions + d->m_csi->update(); + } else { + d->deleteCCTextures(); + } +#endif + + d->m_enabled = enabled; + kDebug(1212) << enabled; +} + +QMap::const_iterator ColorCorrection::regionsBegin(Window w) +{ + Q_D(ColorCorrection); + return d->m_windowRegions.constFind(w); +} + +QMap::const_iterator ColorCorrection::regionsEnd(Window w) +{ + Q_D(ColorCorrection); + QMap::const_iterator it = d->m_windowRegions.constFind(w); + while (it != d->m_windowRegions.constEnd() && it.key() == w) ++it; + return it; +} + +void ColorCorrection::setupForOutput(int screen) +{ + Q_D(ColorCorrection); + + if (!d->m_enabled) + return; + + GLShader *shader = ShaderManager::instance()->getBoundShader(); + if (!shader) { + kError(1212) << "no bound shader for color correction setup"; + return; + } + + if (!shader->setUniform("u_ccLookupTexture", d->m_ccTextureUnit)) { + kError(1212) << "unable to set uniform for the color correction lookup texture"; + } + +#ifndef KWIN_HAVE_OPENGLES + d->setupCCTextures(); + + GLint activeTexture; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); + glActiveTexture(GL_TEXTURE0 + d->m_ccTextureUnit); + glEnable(GL_TEXTURE_3D); + + if (screen < 0 || screen >= d->m_outputCCTextures.count()) { + // Configure with a dummy texture in case something is wrong + Q_ASSERT(d->m_dummyCCTexture != 0); + glBindTexture(GL_TEXTURE_3D, d->m_dummyCCTexture); + } else { + // Everything looks ok, configure with the proper color correctiont texture + glBindTexture(GL_TEXTURE_3D, d->m_outputCCTextures[screen]); + } + + glActiveTexture(activeTexture); +#else + Q_UNUSED(screen); +#endif // KWIN_HAVE_OPENGLES + + d->m_lastOutput = screen; +} + +void ColorCorrection::setupForRegion(const QMap::const_iterator ®ionIt) +{ +#ifndef KWIN_HAVE_OPENGLES + Q_D(ColorCorrection); + const QRect *key = &(*regionIt); + GLuint tex = d->m_regionCCTextures.value(key, d->m_dummyCCTexture); + + // Bind the correct color lookup texture + GLint activeTexture; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); + glActiveTexture(GL_TEXTURE0 + d->m_ccTextureUnit); + glEnable(GL_TEXTURE_3D); + glBindTexture(GL_TEXTURE_3D, tex); + glActiveTexture(activeTexture); +#else + Q_UNUSED(regionIt); +#endif +} + +void ColorCorrection::resetForRegion() +{ + Q_D(ColorCorrection); + setupForOutput(d->m_lastOutput); +} + +void ColorCorrection::reset() +{ + setupForOutput(-1); +} + +QByteArray ColorCorrection::prepareFragmentShader(const QByteArray &sourceCode) +{ + Q_D(ColorCorrection); + + if (!d->m_enabled) + return sourceCode; + + bool sourceIsValid = true; + + /* + * Detect comments to ignore them later + */ + QList< QPair< int, int > > comments; + int beginIndex, endIndex = 0; + int i1, i2; + + enum {ctNone, ctBegin, ctEnd} commentType; + QByteArrayMatcher commentBegin1("/*"), commentBegin2("//"); + QByteArrayMatcher commentEnd1("*/"), commentEnd2("\n"); + + do { + // Determine the next comment begin index + i1 = commentBegin1.indexIn(sourceCode, endIndex); + i2 = commentBegin2.indexIn(sourceCode, endIndex); + if (i1 == -1 && i2 == -1) commentType = ctNone; + else if (i1 == -1) commentType = ctEnd; + else if (i2 == -1) commentType = ctBegin; + else if (i1 < i2) commentType = ctBegin; + else commentType = ctEnd; + if (commentType == ctNone) + break; + + // Determine the comment's end index + if (commentType == ctBegin) { + beginIndex = i1; + endIndex = commentEnd1.indexIn(sourceCode, beginIndex + 2); + } + if (commentType == ctEnd) { + beginIndex = i2; + endIndex = commentEnd2.indexIn(sourceCode, beginIndex + 2); + } + + if (endIndex != -1) { + if (commentType == ctBegin) + endIndex ++; // adjust for "*/" to be removed + if (commentType == ctEnd) + endIndex --; // adjust for "\n" to be kept + comments.append(QPair< int, int >(beginIndex, endIndex)); + } else { + if (commentType == ctBegin) + sourceIsValid = false; + if (commentType == ctEnd) + comments.append(QPair< int, int >(beginIndex, sourceCode.length())); + break; + } + } while (sourceIsValid); + if (!sourceIsValid) + return sourceCode; + + // Create a version of the source code with the comments stripped out + QByteArray cfSource(sourceCode); // comment-free source code + for (int i = comments.size() - 1; i >= 0; -- i) { + beginIndex = comments[i].first; + endIndex = comments[i].second; + cfSource.replace(beginIndex, endIndex - beginIndex + 1, " "); + } + + /* + * Browse through the code while counting braces + * Search for "void main() { ... }: + */ + QByteArrayMatcher braceOpen("{"); + QByteArrayMatcher braceClose("}"); + QByteArrayMatcher voidKeyword("void"); + int levelOfScope = 0; + enum {brNone, brOpen, brClose} braceType; + + int mainFuncBegin = -1; // where "void main" begins + int mainFuncEnd = -1; // at the closing brace of "void main" + bool insideMainFunc = false; + int i = 0; + + do { + // Determine where the next brace is + i1 = braceOpen.indexIn(cfSource, i); + i2 = braceClose.indexIn(cfSource, i); + if (i1 == -1 && i2 == -1) braceType = brNone; + else if (i1 == -1) braceType = brClose; + else if (i2 == -1) braceType = brOpen; + else if (i1 < i2) braceType = brOpen; + else braceType = brClose; + if (braceType == brNone) { + if (levelOfScope > 0) + sourceIsValid = false; + break; + } + + // Handle opening brance (see if is from void main()) + if (braceType == brOpen) { + if (levelOfScope == 0) { + // Need to search between i and i1 (the last '}' and the current '{' + QByteArray section = cfSource.mid(i, i1 - i); + int i_void = -1; + while ((i_void = section.indexOf("void", i_void + 1)) != -1) { + // Extract the subsection that begins with "void" + QByteArray subSection = section.mid(i_void).simplified(); + subSection.replace('(', " ( "); + subSection.replace(')', " ) "); + QList tokens = subSection.split(' '); + for (int i_token = tokens.size() - 1; i_token >= 0; -- i_token) + if (tokens[i_token].trimmed().isEmpty()) + tokens.removeAt(i_token); + if (tokens.size() == 4 && + tokens[0] == "void" && + tokens[1] == "main" && + tokens[2] == "(" && + tokens[3] == ")") { + if (mainFuncBegin != -1) { + sourceIsValid = false; + break; + } + mainFuncBegin = i + i_void; + insideMainFunc = true; + } + } + } + + levelOfScope ++; + i = i1 + 1; + } + + // Handle closing brace (see if it is from void main()) + if (braceType == brClose) { + levelOfScope --; + if (levelOfScope < 0) { + sourceIsValid = false; + break; + } + + if (levelOfScope == 0 && insideMainFunc) { + mainFuncEnd = i2; + insideMainFunc = false; + } + + i = i2 + 1; + } + } while (sourceIsValid); + sourceIsValid = sourceIsValid && mainFuncBegin != -1 && mainFuncEnd != -1; + if (!sourceIsValid) + return sourceCode; + + QByteArray mainFunc = cfSource.mid(mainFuncBegin, mainFuncEnd - mainFuncBegin + 1); + + /* + * Insert color correction variables at the beginning and + * the color correction code at the end of the main function. + * Need to handle return "jumps" inside the main function. + */ + mainFunc.insert(mainFunc.size() - 1, s_ccAlteration); + mainFunc.insert(0, s_ccVars); + + // Search for return statements inside the main function + QByteArrayMatcher returnMatcher("return"); + i = -1; + while ((i = returnMatcher.indexIn(mainFunc, i)) != -1) { + i1 = mainFunc.indexOf(';', i); + mainFunc.insert(i1 + 1, '}'); + mainFunc.insert(i, '{'); + mainFunc.insert(i + 1, s_ccAlteration); + mainFuncEnd += strlen(s_ccAlteration) + 2; + + i = i1 + strlen(s_ccAlteration) + 2; + } + + // Replace the main function + cfSource.replace(mainFuncBegin, mainFuncEnd - mainFuncBegin + 1, mainFunc); + + return cfSource; +} + +void ColorCorrectionPrivate::setupCCTextures() +{ + Q_Q(ColorCorrection); + + if (m_ccTextureUnit < 0) { + GLint maxUnits = 0; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxUnits); + + if (maxUnits < 2) { + kWarning(1212) << "insufficient maximum number of texture units allowed:" << maxUnits; + kWarning(1212) << "color correction will be disabled"; + m_hasError = true; + m_ccTextureUnit = 0; + q->setEnabled(false); + return; + } + + m_ccTextureUnit = maxUnits - 1; + } + + // Dummy texture first + if (!m_dummyCCTexture) { + glGenTextures(1, &m_dummyCCTexture); + setupCCTexture(m_dummyCCTexture, m_dummyClut); + } + + // Setup actual color correction textures + if (m_outputCCTextures.isEmpty() && !m_outputCluts->isEmpty()) { + kDebug(1212) << "setting up output color correction textures"; + + const int outputCount = m_outputCluts->size(); + m_outputCCTextures.resize(outputCount); + glGenTextures(outputCount, m_outputCCTextures.data()); + + for (int i = 0; i < outputCount; ++i) + setupCCTexture(m_outputCCTextures[i], m_outputCluts->at(i)); + } + + if (m_regionCCTextures.isEmpty() && !m_regionCluts->isEmpty()) { + Q_ASSERT(m_windowRegions.isEmpty()); + kDebug(1212) << "setting up region color correction textures"; + + // Generate region textures (and place them inside a map) + RegionalClutMap::const_iterator rcit; + QMap::const_iterator rit; + for (rcit = m_regionCluts->begin(); rcit != m_regionCluts->end(); ++rcit) { + GLuint tex; + glGenTextures(1, &tex); + setupCCTexture(tex, rcit->c); + + // Insert the new texture into the region maps + rit = m_windowRegions.insert(rcit.key(), rcit->r); // this one maps Window -> QRect + m_regionCCTextures.insert(&(*rit), tex); // this one maps QRect* -> texture + } + } + + // TODO Handle errors (what if a texture isn't generated?) +} + +void ColorCorrectionPrivate::deleteCCTextures() +{ + // Delete dummy texture + if (m_dummyCCTexture) { + glDeleteTextures(1, &m_dummyCCTexture); + m_dummyCCTexture = 0; + } + + // Delete actual color correction extures + if (!m_outputCCTextures.isEmpty()) { + glDeleteTextures(m_outputCCTextures.size(), m_outputCCTextures.data()); + m_outputCCTextures.clear(); + } + if (!m_regionCCTextures.isEmpty()) { + QMap::const_iterator it; + for (it = m_regionCCTextures.begin(); it != m_regionCCTextures.end(); ++it) + glDeleteTextures(1, &(*it)); + m_regionCCTextures.clear(); + m_windowRegions.clear(); + } +} + +void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) +{ + if ((uint) clut.size() != CLUT_ELEMENT_COUNT) { + kError(1212) << "cannot setup CC texture: invalid color lookup table"; + return; + } + + kDebug(1212) << texture; + +#ifndef KWIN_HAVE_OPENGLES + glEnable(GL_TEXTURE_3D); + glBindTexture(GL_TEXTURE_3D, texture); + + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16, + LUT_GRID_POINTS, LUT_GRID_POINTS, LUT_GRID_POINTS, + 0, GL_RGB, GL_UNSIGNED_SHORT, clut.data()); + + glDisable(GL_TEXTURE_3D); + + checkGLError("setupCCTexture"); +#else + Q_UNUSED(texture); +#endif // KWIN_HAVE_OPENGLES +} + +void ColorCorrectionPrivate::colorServerUpdateSucceededSlot() +{ + Q_Q(ColorCorrection); + + kDebug(1212) << "Update of color profiles succeeded"; + + // Force the color correction textures to be recreated + deleteCCTextures(); + + emit q->changed(); +} + +void ColorCorrectionPrivate::colorServerUpdateFailedSlot() +{ + Q_Q(ColorCorrection); + + kError(1212) << "Update of color profiles failed"; + + q->setEnabled(false); +} + +} // KWin namespace diff --git a/libkwineffects/kwinglcolorcorrection.h b/libkwineffects/kwinglcolorcorrection.h new file mode 100644 index 0000000000..c2b299745a --- /dev/null +++ b/libkwineffects/kwinglcolorcorrection.h @@ -0,0 +1,143 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2012 Casian Andrei + +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 . +*********************************************************************/ + +#ifndef KWIN_COLOR_CORRECTION_H +#define KWIN_COLOR_CORRECTION_H + +#include "kwinglutils_funcs.h" + +#include +#include +#include + +namespace KWin { + +class ColorCorrectionPrivate; + +/** + * Implements a color correction mechanism. The settings are obtained + * asynchronously via D-Bus from kolor-server, which is part of kolor-manager. + * + * If it fails to get the settings, nothing should happen (no correction), even + * if it is set to enabled. + * + * Supports per-output and per-region correction (window region). + * + * \warning This class is not designed to be used by effects, however + * it may happen to be useful their case somehow. + */ +class KWIN_EXPORT ColorCorrection : public QObject +{ + Q_OBJECT + +public: + static ColorCorrection *instance(); + static void cleanup(); + + /** + * The beginning of a region list for a window \param w + * \return Constant iterator to the beginning + * \see setupForRegion + * + * It can be used to indicate a particular region for which + * to set up color correction. + * + * These regions come from the applications, which communicate with the + * color server (kolor-server in kolor-manager), and this has no direct + * relation to KWin. Consequently, modifying these regions does not + * make sense inside KWin. + */ + QMap::const_iterator regionsBegin(Window w); + + /** + * The ending of a region list for a window \param w + * \return Constant iterator to the ending + * \see setupForRegion + */ + QMap::const_iterator regionsEnd(Window w); + + /** + * Prepares color correction for the output number \param screen. + * Sets up the appropriate color lookup texture for the output. + */ + void setupForOutput(int screen); + + /** + * Prepares color correction for one region of a window (in fact a rect), + * which is indicated by \param regionIt. This can be obtained by iterating + * between \ref regionsBegin and \ref regionsEnd, for that particular window. + * + * \note This should be called when drawing a window + */ + void setupForRegion(const QMap::const_iterator ®ionIt); + + /** + * Disables color correction for a particular window region. Instead, + * color correction is set up again for the last output that was set + * with \ref setupForOutput. + * + * \note This should be called after finishing the drawing of a window. + */ + void resetForRegion(); + + /** + * Unsets color correction by using a dummy color lookup texture. This + * does not disable anything, the CC mechanisms remain in place. Instead, it + * indicates to draw normally. + */ + void reset(); + + /** + * When color correction is disabled, it does nothing and returns + * \param sourceCode. + * + * Else, it modifies \param sourceCode, making it suitable for performing + * color correction. This is done by inserting a 3d texture lookup operation + * just before the output fragment color is returned. + */ + QByteArray prepareFragmentShader(const QByteArray &sourceCode); + +public slots: + /** + * Enables or disables color correction. Compositing should be restarted + * for changes to take effect. + */ + void setEnabled(bool enabled); + +signals: + /** + * Emitted when some changes happened to the color correction settings, and + * a full repaint of the scene should be done to make the new settings visible. + */ + void changed(); + +private: + ColorCorrection(); + virtual ~ColorCorrection(); + +private: + ColorCorrectionPrivate *d_ptr; + Q_DECLARE_PRIVATE(ColorCorrection) + static ColorCorrection *s_colorCorrection; +}; + +} // KWin namespace + +#endif // KWIN_COLOR_CORRECTION_H diff --git a/libkwineffects/kwinglcolorcorrection_p.h b/libkwineffects/kwinglcolorcorrection_p.h new file mode 100644 index 0000000000..e244d01035 --- /dev/null +++ b/libkwineffects/kwinglcolorcorrection_p.h @@ -0,0 +1,168 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2012 Casian Andrei + +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 . +*********************************************************************/ + +#ifndef KWIN_COLOR_CORRECTION_P_H_ +#define KWIN_COLOR_CORRECTION_P_H_ + +#include "kwinglcolorcorrection.h" + +#include +#include +#include +#include +#include + +class QDBusPendingCallWatcher; + +/* + * Clut + * All this should be the same as in the color server code, in kolor-manager + */ +typedef QVector Clut; +typedef QList ClutList; +typedef struct { QRect r; Clut c; } RegionalClut; +typedef QMultiMap RegionalClutMap; + +Q_DECLARE_METATYPE(Clut) +Q_DECLARE_METATYPE(ClutList) +Q_DECLARE_METATYPE(RegionalClut) +Q_DECLARE_METATYPE(RegionalClutMap) + +// Marshall the RegionalClut data into a D-Bus argument +inline QDBusArgument &operator<<(QDBusArgument &argument, const RegionalClut &rc) +{ + argument.beginStructure(); + argument << rc.r << rc.c; + argument.endStructure(); + return argument; +} + +// Retrieve the RegionalClut data from the D-Bus argument +inline const QDBusArgument &operator>>(const QDBusArgument &argument, RegionalClut &rc) +{ + argument.beginStructure(); + argument >> rc.r >> rc.c; + argument.endStructure(); + return argument; +} + + +namespace KWin { + +class ColorServerInterface; + + +/* + * Color Correction Private Data + */ +class ColorCorrectionPrivate : public QObject +{ + Q_OBJECT + +public: + explicit ColorCorrectionPrivate(ColorCorrection* parent); + virtual ~ColorCorrectionPrivate(); + + void setupCCTextures(); + void deleteCCTextures(); + static void setupCCTexture(GLuint texture, const Clut &clut); + +public slots: + void colorServerUpdateSucceededSlot(); + void colorServerUpdateFailedSlot(); + +public: + bool m_enabled; + bool m_hasError; + int m_ccTextureUnit; + + ColorServerInterface *m_csi; + const ClutList *m_outputCluts; + QVector m_outputCCTextures; + const RegionalClutMap *m_regionCluts; + QMultiMap m_windowRegions; + QMap m_regionCCTextures; // keys from m_regions's values + Clut m_dummyClut; + GLuint m_dummyCCTexture; + + int m_lastOutput; + +private: + ColorCorrection *q_ptr; + Q_DECLARE_PUBLIC(ColorCorrection); +}; + + +/* + * Color Server DBus interface + */ +class ColorServerInterface : public QDBusAbstractInterface +{ + Q_OBJECT + +public: + static inline const char *staticInterfaceName() + { return "org.kde.KolorServer"; } + +public: + ColorServerInterface(const QString &service, + const QString &path, + const QDBusConnection &connection, + QObject *parent = 0); + virtual ~ColorServerInterface(); + + uint versionInfo() const; + const ClutList& outputCluts() const; + const RegionalClutMap& regionCluts() const; + +public slots: + void update(); + +signals: + void updateSucceeded(); + void updateFailed(); + void outputClutsChanged(); + void regionClutsChanged(); + +private: + QDBusPendingReply< uint > getVersionInfo(); + QDBusPendingReply< ClutList > getOutputCluts(); + QDBusPendingReply< RegionalClutMap > getRegionCluts(); + +private slots: + void callFinishedSlot(QDBusPendingCallWatcher *watcher); + +private: + QDBusPendingCallWatcher *m_versionInfoWatcher; + QDBusPendingCallWatcher *m_outputClutsWatcher; + QDBusPendingCallWatcher *m_regionClutsWatcher; + bool m_versionInfoUpdated; + bool m_outputClutsUpdated; + bool m_regionClutsUpdated; + uint m_versionInfo; + ClutList m_outputCluts; + RegionalClutMap m_regionCluts; + + bool m_signaledFail; +}; + +} // KWin namespace + +#endif // KWIN_COLOR_CORRECTION_P_H_ diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index 016d31efc8..edddc0d6a1 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -24,6 +24,7 @@ along with this program. If not, see . // need to call GLTexturePrivate::initStatic() #include "kwingltexture_p.h" +#include "kwinglcolorcorrection.h" #include "kwinglobals.h" #include "kwineffects.h" #include "kwinglplatform.h" @@ -304,10 +305,8 @@ bool GLShader::loadFromFiles(const QString &vertexFile, const QString &fragmentF return load(vertexSource, fragmentSource); } -bool GLShader::compile(GLuint program, GLenum shaderType, const QByteArray &source) const +const QByteArray GLShader::prepareSource(GLenum shaderType, const QByteArray &source) const { - GLuint shader = glCreateShader(shaderType); - // Prepare the source code QByteArray ba; #ifdef KWIN_HAVE_OPENGLES @@ -318,7 +317,19 @@ bool GLShader::compile(GLuint program, GLenum shaderType, const QByteArray &sour } ba.append(source); - const char* src = ba.constData(); + // Inject color correction code for fragment shaders, if possible + if (shaderType == GL_FRAGMENT_SHADER) + ba = ColorCorrection::instance()->prepareFragmentShader(ba); + + return ba; +} + +bool GLShader::compile(GLuint program, GLenum shaderType, const QByteArray &source) const +{ + GLuint shader = glCreateShader(shaderType); + + QByteArray preparedSource = prepareSource(shaderType, source); + const char* src = preparedSource.constData(); glShaderSource(shader, 1, &src, NULL); // Compile the shader diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 7a7c3c96ee..7f092a5772 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -204,6 +204,7 @@ protected: GLShader(); bool loadFromFiles(const QString& vertexfile, const QString& fragmentfile); bool load(const QByteArray &vertexSource, const QByteArray &fragmentSource); + const QByteArray prepareSource(GLenum shaderType, const QByteArray &sourceCode) const; bool compile(GLuint program, GLenum shaderType, const QByteArray &sourceCode) const; void bind(); void unbind(); diff --git a/options.cpp b/options.cpp index 72f168d94a..bba9eb7687 100644 --- a/options.cpp +++ b/options.cpp @@ -148,6 +148,7 @@ Options::Options(QObject *parent) , m_unredirectFullscreen(Options::defaultUnredirectFullscreen()) , m_glSmoothScale(Options::defaultGlSmoothScale()) , m_glVSync(Options::defaultGlVSync()) + , m_glColorCorrection(Options::defaultGlColorCorrection()) , m_xrenderSmoothScale(Options::defaultXrenderSmoothScale()) , m_maxFpsInterval(Options::defaultMaxFpsInterval()) , m_refreshRate(Options::defaultRefreshRate()) @@ -697,6 +698,15 @@ void Options::setGlVSync(bool glVSync) emit glVSyncChanged(); } +void Options::setGlColorCorrection(bool glColorCorrection) +{ + if (m_glColorCorrection == glColorCorrection) { + return; + } + m_glColorCorrection = glColorCorrection; + emit glColorCorrectionChanged(); +} + void Options::setXrenderSmoothScale(bool xrenderSmoothScale) { if (m_xrenderSmoothScale == xrenderSmoothScale) { @@ -979,6 +989,7 @@ void Options::reloadCompositingSettings(bool force) setGlDirect(prefs.enableDirectRendering()); setGlVSync(config.readEntry("GLVSync", Options::defaultGlVSync())); + setGlColorCorrection(config.readEntry("GLColorCorrection", Options::defaultGlColorCorrection())); setGlSmoothScale(qBound(-1, config.readEntry("GLTextureFilter", Options::defaultGlSmoothScale()), 2)); setGlStrictBindingFollowsDriver(!config.hasKey("GLStrictBinding")); if (!isGlStrictBindingFollowsDriver()) { diff --git a/options.h b/options.h index 9e4fcc682e..42e0e4abb7 100644 --- a/options.h +++ b/options.h @@ -179,6 +179,7 @@ class Options : public QObject, public KDecorationOptions **/ Q_PROPERTY(int glSmoothScale READ glSmoothScale WRITE setGlSmoothScale NOTIFY glSmoothScaleChanged) Q_PROPERTY(bool glVSync READ isGlVSync WRITE setGlVSync NOTIFY glVSyncChanged) + Q_PROPERTY(bool glColorCorrection READ isGlColorCorrection WRITE setGlColorCorrection NOTIFY glColorCorrectionChanged) Q_PROPERTY(bool xrenderSmoothScale READ isXrenderSmoothScale WRITE setXrenderSmoothScale NOTIFY xrenderSmoothScaleChanged) Q_PROPERTY(uint maxFpsInterval READ maxFpsInterval WRITE setMaxFpsInterval NOTIFY maxFpsIntervalChanged) Q_PROPERTY(uint refreshRate READ refreshRate WRITE setRefreshRate NOTIFY refreshRateChanged) @@ -538,6 +539,9 @@ public: bool isGlVSync() const { return m_glVSync; } + bool isGlColorCorrection() const { + return m_glColorCorrection; + } // XRender bool isXrenderSmoothScale() const { return m_xrenderSmoothScale; @@ -617,6 +621,7 @@ public: void setUnredirectFullscreen(bool unredirectFullscreen); void setGlSmoothScale(int glSmoothScale); void setGlVSync(bool glVSync); + void setGlColorCorrection(bool glColorCorrection); void setXrenderSmoothScale(bool xrenderSmoothScale); void setMaxFpsInterval(uint maxFpsInterval); void setRefreshRate(uint refreshRate); @@ -819,6 +824,9 @@ public: static bool defaultGlVSync() { return true; } + static bool defaultGlColorCorrection() { + return false; + } static bool defaultXrenderSmoothScale() { return false; } @@ -916,6 +924,7 @@ Q_SIGNALS: void unredirectFullscreenChanged(); void glSmoothScaleChanged(); void glVSyncChanged(); + void glColorCorrectionChanged(); void xrenderSmoothScaleChanged(); void maxFpsIntervalChanged(); void refreshRateChanged(); @@ -958,6 +967,7 @@ private: bool m_unredirectFullscreen; int m_glSmoothScale; bool m_glVSync; + bool m_glColorCorrection; bool m_xrenderSmoothScale; uint m_maxFpsInterval; // Settings that should be auto-detected diff --git a/scene.cpp b/scene.cpp index 578251014c..f4a3bdf531 100644 --- a/scene.cpp +++ b/scene.cpp @@ -75,12 +75,10 @@ along with this program. If not, see . #include #include -#include #include "client.h" #include "deleted.h" #include "effects.h" -#include "lanczosfilter.h" #include "overlaywindow.h" #include "shadow.h" @@ -437,16 +435,7 @@ void Scene::finalPaintWindow(EffectWindowImpl* w, int mask, QRegion region, Wind // will be eventually called from drawWindow() void Scene::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) { - if (mask & PAINT_WINDOW_LANCZOS) { - if (lanczos_filter.isNull()) { - lanczos_filter = new LanczosFilter(this); - // recreate the lanczos filter when the screen gets resized - connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), lanczos_filter.data(), SLOT(deleteLater())); - connect(QApplication::desktop(), SIGNAL(resized(int)), lanczos_filter.data(), SLOT(deleteLater())); - } - lanczos_filter.data()->performPaint(w, mask, region, data); - } else - w->sceneWindow()->performPaint(mask, region, data); + w->sceneWindow()->performPaint(mask, region, data); } OverlayWindow* Scene::overlayWindow() diff --git a/scene.h b/scene.h index 38911986f8..feb91c7483 100644 --- a/scene.h +++ b/scene.h @@ -124,7 +124,7 @@ protected: // shared implementation, starts painting the window virtual void paintWindow(Window* w, int mask, QRegion region, WindowQuadList quads); // called after all effects had their drawWindow() called - void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); + virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); // compute time since the last repaint void updateTimeDiff(); // saved data for 2nd pass of optimized screen painting diff --git a/scene_opengl.cpp b/scene_opengl.cpp index cbcc0cabdd..fe8bc9793c 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -70,12 +70,14 @@ Sources and other compositing managers: #include +#include #include #include "utils.h" #include "client.h" #include "deleted.h" #include "effects.h" +#include "lanczosfilter.h" #include "overlaywindow.h" #include @@ -87,6 +89,7 @@ Sources and other compositing managers: #include #include +#include #include #include #include @@ -205,6 +208,38 @@ void SceneOpenGL::paintBackground(QRegion region) } } +void SceneOpenGL::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) +{ + if (options->isGlColorCorrection()) { + // Split the painting for separate screens + int numScreens = Workspace::self()->numScreens(); + for (int screen = 0; screen < numScreens; ++ screen) { + QRegion regionForScreen(region); + if (numScreens > 1) + regionForScreen = region.intersected(Workspace::self()->screenGeometry(screen)); + + data.setScreen(screen); + performPaint(w, mask, regionForScreen, data); + } + } else { + performPaint(w, mask, region, data); + } +} + +void SceneOpenGL::performPaint(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) +{ + if (mask & PAINT_WINDOW_LANCZOS) { + if (lanczos_filter.isNull()) { + lanczos_filter = new LanczosFilter(this); + // recreate the lanczos filter when the screen gets resized + connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), lanczos_filter.data(), SLOT(deleteLater())); + connect(QApplication::desktop(), SIGNAL(resized(int)), lanczos_filter.data(), SLOT(deleteLater())); + } + lanczos_filter.data()->performPaint(w, mask, region, data); + } else + w->sceneWindow()->performPaint(mask, region, data); +} + void SceneOpenGL::windowAdded(Toplevel* c) { assert(!windows.contains(c)); @@ -489,6 +524,8 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data.shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); data.shader->setUniform(GLShader::Offset, QVector2D(x(), y())); } + if (options->isGlColorCorrection()) + ColorCorrection::instance()->setupForOutput(data.screen()); sceneShader = true; } @@ -573,9 +610,9 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData WindowQuadList contentQuads = data.quads.select(WindowQuadContents); if (!contentQuads.empty()) { texture.bind(); - prepareStates(Content, data.opacity(), data.brightness(), data.saturation(), data.shader); + prepareStates(Content, data.opacity(), data.brightness(), data.saturation(), data.screen(), data.shader); renderQuads(mask, region, contentQuads, &texture, false, hardwareClipping); - restoreStates(Content, data.opacity(), data.brightness(), data.saturation(), data.shader); + restoreStates(Content, data.opacity(), data.brightness(), data.saturation(), data.screen(), data.shader); texture.unbind(); #ifndef KWIN_HAVE_OPENGLES if (static_cast(scene)->debug) { @@ -646,10 +683,10 @@ void SceneOpenGL::Window::paintDecoration(const QPixmap* decoration, TextureType decorationTexture->setWrapMode(GL_CLAMP_TO_EDGE); decorationTexture->bind(); - prepareStates(decorationType, data.opacity() * data.decorationOpacity(), data.brightness(), data.saturation(), data.shader); + prepareStates(decorationType, data.opacity() * data.decorationOpacity(), data.brightness(), data.saturation(), data.screen(), data.shader); makeDecorationArrays(quads, rect, decorationTexture); GLVertexBuffer::streamingBuffer()->render(region, GL_TRIANGLES, hardwareClipping); - restoreStates(decorationType, data.opacity() * data.decorationOpacity(), data.brightness(), data.saturation(), data.shader); + restoreStates(decorationType, data.opacity() * data.decorationOpacity(), data.brightness(), data.saturation(), data.screen(), data.shader); decorationTexture->unbind(); #ifndef KWIN_HAVE_OPENGLES if (static_cast(scene)->debug) { @@ -683,9 +720,9 @@ void SceneOpenGL::Window::paintShadow(const QRegion ®ion, const WindowPaintDa texture->setFilter(GL_NEAREST); texture->setWrapMode(GL_CLAMP_TO_EDGE); texture->bind(); - prepareStates(Shadow, data.opacity(), data.brightness(), data.saturation(), data.shader, texture); + prepareStates(Shadow, data.opacity(), data.brightness(), data.saturation(), data.screen(), data.shader, texture); renderQuads(0, region, quads, texture, true, hardwareClipping); - restoreStates(Shadow, data.opacity(), data.brightness(), data.saturation(), data.shader, texture); + restoreStates(Shadow, data.opacity(), data.brightness(), data.saturation(), data.screen(), data.shader, texture); texture->unbind(); #ifndef KWIN_HAVE_OPENGLES if (static_cast(scene)->debug) { @@ -781,10 +818,10 @@ void SceneOpenGL::Window::renderQuads(int, const QRegion& region, const WindowQu delete[] texcoords; } -void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader) +void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader) { if (shader) - prepareShaderRenderStates(type, opacity, brightness, saturation, shader); + prepareShaderRenderStates(type, opacity, brightness, saturation, screen, shader); else { Texture *tex = NULL; switch(type) { @@ -806,20 +843,20 @@ void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double default: return; } - prepareStates(type, opacity, brightness, saturation, shader, tex); + prepareStates(type, opacity, brightness, saturation, screen, shader, tex); } } -void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, GLTexture *texture) +void SceneOpenGL::Window::prepareStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader, GLTexture *texture) { if (shader) { - prepareShaderRenderStates(type, opacity, brightness, saturation, shader); + prepareShaderRenderStates(type, opacity, brightness, saturation, screen, shader); } else { - prepareRenderStates(type, opacity, brightness, saturation, texture); + prepareRenderStates(type, opacity, brightness, saturation, screen, texture); } } -void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader) +void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader) { // setup blending of transparent windows bool opaque = isOpaque() && opacity == 1.0; @@ -828,12 +865,15 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa opaque = false; if (!opaque) { glEnable(GL_BLEND); - if (alpha) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } else { - glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity); - glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); - } + if (!options->isGlColorCorrection()) { + if (alpha) { + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity); + glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); + } + } else + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } const float rgb = brightness * opacity; @@ -842,10 +882,14 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, saturation); shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0); + + if (options->isGlColorCorrection()) + ColorCorrection::instance()->setupForOutput(screen); } -void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, GLTexture *tex) +void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLTexture *tex) { + Q_UNUSED(screen) #ifdef KWIN_HAVE_OPENGLES Q_UNUSED(type) Q_UNUSED(opacity) @@ -980,10 +1024,10 @@ void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, #endif } -void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader) +void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader) { if (shader) - restoreShaderRenderStates(type, opacity, brightness, saturation, shader); + restoreShaderRenderStates(type, opacity, brightness, saturation, screen, shader); else { Texture *tex = NULL; switch(type) { @@ -1005,23 +1049,24 @@ void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double default: return; } - restoreStates(type, opacity, brightness, saturation, shader, tex); + restoreStates(type, opacity, brightness, saturation, screen, shader, tex); } } -void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, GLTexture *texture) +void SceneOpenGL::Window::restoreStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader, GLTexture *texture) { if (shader) { - restoreShaderRenderStates(type, opacity, brightness, saturation, shader); + restoreShaderRenderStates(type, opacity, brightness, saturation, screen, shader); } else { - restoreRenderStates(type, opacity, brightness, saturation, texture); + restoreRenderStates(type, opacity, brightness, saturation, screen, texture); } } -void SceneOpenGL::Window::restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader) +void SceneOpenGL::Window::restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader) { Q_UNUSED(brightness); Q_UNUSED(saturation); + Q_UNUSED(screen) Q_UNUSED(shader); bool opaque = isOpaque() && opacity == 1.0; if (type != Content) @@ -1032,9 +1077,10 @@ void SceneOpenGL::Window::restoreShaderRenderStates(TextureType type, double opa ShaderManager::instance()->getBoundShader()->setUniform(GLShader::AlphaToOne, 0); } -void SceneOpenGL::Window::restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, GLTexture *tex) +void SceneOpenGL::Window::restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLTexture *tex) { Q_UNUSED(type) + Q_UNUSED(screen) #ifdef KWIN_HAVE_OPENGLES Q_UNUSED(opacity) Q_UNUSED(brightness) diff --git a/scene_opengl.h b/scene_opengl.h index de33ce4d00..68406b2766 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -56,6 +56,8 @@ public: protected: virtual void paintGenericScreen(int mask, ScreenPaintData data); virtual void paintBackground(QRegion region); + virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); + virtual void performPaint(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const; public Q_SLOTS: virtual void windowOpacityChanged(KWin::Toplevel* c); @@ -184,14 +186,14 @@ protected: void paintShadow(const QRegion ®ion, const WindowPaintData &data, bool hardwareClipping); void makeDecorationArrays(const WindowQuadList& quads, const QRect &rect, Texture *tex) const; void renderQuads(int, const QRegion& region, const WindowQuadList& quads, GLTexture* tex, bool normalized, bool hardwareClipping); - void prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader); - void prepareStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, GLTexture *texture); - void prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, GLTexture *tex); - void prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader); - void restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader); - void restoreStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader, GLTexture *texture); - void restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, GLTexture *tex); - void restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, GLShader* shader); + void prepareStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader); + void prepareStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader, GLTexture *texture); + void prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLTexture *tex); + void prepareShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader); + void restoreStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader); + void restoreStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader, GLTexture *texture); + void restoreRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLTexture *tex); + void restoreShaderRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLShader* shader); private: Texture texture; diff --git a/workspace.cpp b/workspace.cpp index ecf0d76cfc..148b60d73a 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -191,6 +191,7 @@ Workspace::Workspace(bool restore) connect(&rulesUpdatedTimer, SIGNAL(timeout()), this, SLOT(writeWindowRules())); connect(&unredirectTimer, SIGNAL(timeout()), this, SLOT(delayedCheckUnredirect())); connect(&compositeResetTimer, SIGNAL(timeout()), this, SLOT(resetCompositing())); + connect(options, SIGNAL(glColorCorrectionChanged()), this, SLOT(resetCompositing())); unredirectTimer.setSingleShot(true); compositeResetTimer.setSingleShot(true); From fadb6636af909a7157d02c233be152fe4ab050f6 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Fri, 24 Aug 2012 17:07:13 +0300 Subject: [PATCH 02/20] CC: No html translatable text. Only

and remaining --- kcmkwin/kwincompositing/main.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kcmkwin/kwincompositing/main.ui b/kcmkwin/kwincompositing/main.ui index fcac221ed2..09623a82ab 100644 --- a/kcmkwin/kwincompositing/main.ui +++ b/kcmkwin/kwincompositing/main.ui @@ -805,7 +805,7 @@ On legacy hardware disabling Shaders can improve the performance. false - <html><head/><body><p>Activates color correction if possible, using the Kolor-Manager. Requires OpenGL 2 Shaders to be enabled and <span style=" text-decoration: underline;">Kolor-Manager to be installed</span>. May fail silently.</p><p><span style=" font-weight:600;">Experimental.</span></p></body></html> + <p>Activates color correction if possible, using the Kolor-Manager. Requires OpenGL 2 Shaders to be enabled and Kolor-Manager to be installed. May fail silently.</p><p><strong>Experimental</strong>.</p> Enable color correction (experimental) From 2afa88a889a2565bac9a565a9cb7b9534486b3ec Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Fri, 24 Aug 2012 17:08:11 +0300 Subject: [PATCH 03/20] CC: int instead of qint32 --- libkwineffects/kwineffects.cpp | 6 +++--- libkwineffects/kwineffects.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index 1f82da7b33..fcbea51480 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -211,7 +211,7 @@ public: qreal decorationOpacity; qreal saturation; qreal brightness; - qint32 screen; + int screen; }; WindowPaintData::WindowPaintData(EffectWindow* w) @@ -272,7 +272,7 @@ qreal WindowPaintData::brightness() const return d->brightness; } -qint32 WindowPaintData::screen() const +int WindowPaintData::screen() const { return d->screen; } @@ -297,7 +297,7 @@ void WindowPaintData::setBrightness(qreal brightness) d->brightness = brightness; } -void WindowPaintData::setScreen(qint32 screen) const +void WindowPaintData::setScreen(int screen) const { d->screen = screen; } diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index bd2e8f2897..e54d9d3e5e 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1943,12 +1943,12 @@ public: * color correction lookup tables because they have different ICC profiles). * @return screen for which painting should be done */ - qint32 screen() const; + int screen() const; /** * @param screen New screen number * A value less than 0 will indicate that a default profile should be done. */ - void setScreen(qint32 screen) const; + void setScreen(int screen) const; WindowQuadList quads; /** * Shader to be used for rendering, if any. From 7d331ea7ff1101fedb8765817d247c4139cbe141 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 15:29:59 +0300 Subject: [PATCH 04/20] CC: Rename "glColorCorrection" property to "colorCorrected" --- composite.cpp | 4 ++-- options.cpp | 13 +++++++------ options.h | 14 +++++++------- scene_opengl.cpp | 8 ++++---- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/composite.cpp b/composite.cpp index f1823f5969..57e0df5090 100644 --- a/composite.cpp +++ b/composite.cpp @@ -142,8 +142,8 @@ void Workspace::slotCompositingOptionsInitialized() } #endif - kDebug(1212) << "Color correction:" << options->isGlColorCorrection(); - ColorCorrection::instance()->setEnabled(options->isGlColorCorrection()); + kDebug(1212) << "Color correction:" << options->isColorCorrected(); + ColorCorrection::instance()->setEnabled(options->isColorCorrected()); connect(ColorCorrection::instance(), SIGNAL(changed()), this, SLOT(addRepaintFull())); scene = new SceneOpenGL(this); diff --git a/options.cpp b/options.cpp index bba9eb7687..ba40fdbe9a 100644 --- a/options.cpp +++ b/options.cpp @@ -148,7 +148,7 @@ Options::Options(QObject *parent) , m_unredirectFullscreen(Options::defaultUnredirectFullscreen()) , m_glSmoothScale(Options::defaultGlSmoothScale()) , m_glVSync(Options::defaultGlVSync()) - , m_glColorCorrection(Options::defaultGlColorCorrection()) + , m_colorCorrected(Options::defaultColorCorrected()) , m_xrenderSmoothScale(Options::defaultXrenderSmoothScale()) , m_maxFpsInterval(Options::defaultMaxFpsInterval()) , m_refreshRate(Options::defaultRefreshRate()) @@ -698,13 +698,13 @@ void Options::setGlVSync(bool glVSync) emit glVSyncChanged(); } -void Options::setGlColorCorrection(bool glColorCorrection) +void Options::setColorCorrected(bool colorCorrected) { - if (m_glColorCorrection == glColorCorrection) { + if (m_colorCorrected == colorCorrected) { return; } - m_glColorCorrection = glColorCorrection; - emit glColorCorrectionChanged(); + m_colorCorrected = colorCorrected; + emit colorCorrectedChanged(); } void Options::setXrenderSmoothScale(bool xrenderSmoothScale) @@ -989,13 +989,14 @@ void Options::reloadCompositingSettings(bool force) setGlDirect(prefs.enableDirectRendering()); setGlVSync(config.readEntry("GLVSync", Options::defaultGlVSync())); - setGlColorCorrection(config.readEntry("GLColorCorrection", Options::defaultGlColorCorrection())); setGlSmoothScale(qBound(-1, config.readEntry("GLTextureFilter", Options::defaultGlSmoothScale()), 2)); setGlStrictBindingFollowsDriver(!config.hasKey("GLStrictBinding")); if (!isGlStrictBindingFollowsDriver()) { setGlStrictBinding(config.readEntry("GLStrictBinding", Options::defaultGlStrictBinding())); } + setColorCorrected(config.readEntry("GLColorCorrection", Options::defaultColorCorrected())); + m_xrenderSmoothScale = config.readEntry("XRenderSmoothScale", false); HiddenPreviews previews = Options::defaultHiddenPreviews(); diff --git a/options.h b/options.h index 42e0e4abb7..29aa8be365 100644 --- a/options.h +++ b/options.h @@ -179,7 +179,7 @@ class Options : public QObject, public KDecorationOptions **/ Q_PROPERTY(int glSmoothScale READ glSmoothScale WRITE setGlSmoothScale NOTIFY glSmoothScaleChanged) Q_PROPERTY(bool glVSync READ isGlVSync WRITE setGlVSync NOTIFY glVSyncChanged) - Q_PROPERTY(bool glColorCorrection READ isGlColorCorrection WRITE setGlColorCorrection NOTIFY glColorCorrectionChanged) + Q_PROPERTY(bool colorCorrected READ isColorCorrected WRITE setColorCorrected NOTIFY colorCorrectedChanged) Q_PROPERTY(bool xrenderSmoothScale READ isXrenderSmoothScale WRITE setXrenderSmoothScale NOTIFY xrenderSmoothScaleChanged) Q_PROPERTY(uint maxFpsInterval READ maxFpsInterval WRITE setMaxFpsInterval NOTIFY maxFpsIntervalChanged) Q_PROPERTY(uint refreshRate READ refreshRate WRITE setRefreshRate NOTIFY refreshRateChanged) @@ -539,8 +539,8 @@ public: bool isGlVSync() const { return m_glVSync; } - bool isGlColorCorrection() const { - return m_glColorCorrection; + bool isColorCorrected() const { + return m_colorCorrected; } // XRender bool isXrenderSmoothScale() const { @@ -621,7 +621,7 @@ public: void setUnredirectFullscreen(bool unredirectFullscreen); void setGlSmoothScale(int glSmoothScale); void setGlVSync(bool glVSync); - void setGlColorCorrection(bool glColorCorrection); + void setColorCorrected(bool colorCorrected); void setXrenderSmoothScale(bool xrenderSmoothScale); void setMaxFpsInterval(uint maxFpsInterval); void setRefreshRate(uint refreshRate); @@ -824,7 +824,7 @@ public: static bool defaultGlVSync() { return true; } - static bool defaultGlColorCorrection() { + static bool defaultColorCorrected() { return false; } static bool defaultXrenderSmoothScale() { @@ -924,7 +924,7 @@ Q_SIGNALS: void unredirectFullscreenChanged(); void glSmoothScaleChanged(); void glVSyncChanged(); - void glColorCorrectionChanged(); + void colorCorrectedChanged(); void xrenderSmoothScaleChanged(); void maxFpsIntervalChanged(); void refreshRateChanged(); @@ -967,7 +967,7 @@ private: bool m_unredirectFullscreen; int m_glSmoothScale; bool m_glVSync; - bool m_glColorCorrection; + bool m_colorCorrected; bool m_xrenderSmoothScale; uint m_maxFpsInterval; // Settings that should be auto-detected diff --git a/scene_opengl.cpp b/scene_opengl.cpp index fe8bc9793c..dc1c372a6d 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -210,7 +210,7 @@ void SceneOpenGL::paintBackground(QRegion region) void SceneOpenGL::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) { - if (options->isGlColorCorrection()) { + if (options->isColorCorrected()) { // Split the painting for separate screens int numScreens = Workspace::self()->numScreens(); for (int screen = 0; screen < numScreens; ++ screen) { @@ -524,7 +524,7 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data.shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); data.shader->setUniform(GLShader::Offset, QVector2D(x(), y())); } - if (options->isGlColorCorrection()) + if (options->isColorCorrected()) ColorCorrection::instance()->setupForOutput(data.screen()); sceneShader = true; } @@ -865,7 +865,7 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa opaque = false; if (!opaque) { glEnable(GL_BLEND); - if (!options->isGlColorCorrection()) { + if (!options->isColorCorrected()) { if (alpha) { glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -883,7 +883,7 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa shader->setUniform(GLShader::Saturation, saturation); shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0); - if (options->isGlColorCorrection()) + if (options->isColorCorrected()) ColorCorrection::instance()->setupForOutput(screen); } From c42797637b40bc62430dd816c977fdadd622be8e Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 15:34:51 +0300 Subject: [PATCH 05/20] CC: Constify d_ptr --- libkwineffects/kwinglcolorcorrection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libkwineffects/kwinglcolorcorrection.h b/libkwineffects/kwinglcolorcorrection.h index c2b299745a..ee2497f21d 100644 --- a/libkwineffects/kwinglcolorcorrection.h +++ b/libkwineffects/kwinglcolorcorrection.h @@ -133,7 +133,7 @@ private: virtual ~ColorCorrection(); private: - ColorCorrectionPrivate *d_ptr; + ColorCorrectionPrivate * const d_ptr; Q_DECLARE_PRIVATE(ColorCorrection) static ColorCorrection *s_colorCorrection; }; From 23f3b2a571392b48f1c48a504c24408af38a56ae Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 15:41:46 +0300 Subject: [PATCH 06/20] CC: Rename performPaint to performPaintWindow and make it non-virtual --- scene_opengl.cpp | 6 +++--- scene_opengl.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index dc1c372a6d..668453a1d7 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -219,14 +219,14 @@ void SceneOpenGL::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, regionForScreen = region.intersected(Workspace::self()->screenGeometry(screen)); data.setScreen(screen); - performPaint(w, mask, regionForScreen, data); + performPaintWindow(w, mask, regionForScreen, data); } } else { - performPaint(w, mask, region, data); + performPaintWindow(w, mask, region, data); } } -void SceneOpenGL::performPaint(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) +void SceneOpenGL::performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) { if (mask & PAINT_WINDOW_LANCZOS) { if (lanczos_filter.isNull()) { diff --git a/scene_opengl.h b/scene_opengl.h index 68406b2766..b92f40f013 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -57,7 +57,6 @@ protected: virtual void paintGenericScreen(int mask, ScreenPaintData data); virtual void paintBackground(QRegion region); virtual void finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); - virtual void performPaint(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const; public Q_SLOTS: virtual void windowOpacityChanged(KWin::Toplevel* c); @@ -75,6 +74,7 @@ private: void setupModelViewProjectionMatrix(); #endif void flushBuffer(int mask, QRegion damage); + void performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); GC gcroot; class FBConfigInfo { From 34bcf10c51f9e7c97c5bf844bc788afd318f3991 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 15:48:18 +0300 Subject: [PATCH 07/20] CC: Remove unused code related to regions, until they get implemented --- libkwineffects/kwinglcolorcorrection.cpp | 65 ------------------------ libkwineffects/kwinglcolorcorrection.h | 40 --------------- libkwineffects/kwinglcolorcorrection_p.h | 3 -- 3 files changed, 108 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index 3c066fb4c7..a274827172 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -268,7 +268,6 @@ ColorCorrectionPrivate::ColorCorrectionPrivate(ColorCorrection *parent) this); m_outputCluts = &m_csi->outputCluts(); - m_regionCluts = &m_csi->regionCluts(); connect(m_csi, SIGNAL(updateSucceeded()), this, SLOT(colorServerUpdateSucceededSlot())); connect(m_csi, SIGNAL(updateFailed()), this, SLOT(colorServerUpdateFailedSlot())); @@ -309,20 +308,6 @@ void ColorCorrection::setEnabled(bool enabled) kDebug(1212) << enabled; } -QMap::const_iterator ColorCorrection::regionsBegin(Window w) -{ - Q_D(ColorCorrection); - return d->m_windowRegions.constFind(w); -} - -QMap::const_iterator ColorCorrection::regionsEnd(Window w) -{ - Q_D(ColorCorrection); - QMap::const_iterator it = d->m_windowRegions.constFind(w); - while (it != d->m_windowRegions.constEnd() && it.key() == w) ++it; - return it; -} - void ColorCorrection::setupForOutput(int screen) { Q_D(ColorCorrection); @@ -365,31 +350,6 @@ void ColorCorrection::setupForOutput(int screen) d->m_lastOutput = screen; } -void ColorCorrection::setupForRegion(const QMap::const_iterator ®ionIt) -{ -#ifndef KWIN_HAVE_OPENGLES - Q_D(ColorCorrection); - const QRect *key = &(*regionIt); - GLuint tex = d->m_regionCCTextures.value(key, d->m_dummyCCTexture); - - // Bind the correct color lookup texture - GLint activeTexture; - glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); - glActiveTexture(GL_TEXTURE0 + d->m_ccTextureUnit); - glEnable(GL_TEXTURE_3D); - glBindTexture(GL_TEXTURE_3D, tex); - glActiveTexture(activeTexture); -#else - Q_UNUSED(regionIt); -#endif -} - -void ColorCorrection::resetForRegion() -{ - Q_D(ColorCorrection); - setupForOutput(d->m_lastOutput); -} - void ColorCorrection::reset() { setupForOutput(-1); @@ -613,24 +573,6 @@ void ColorCorrectionPrivate::setupCCTextures() setupCCTexture(m_outputCCTextures[i], m_outputCluts->at(i)); } - if (m_regionCCTextures.isEmpty() && !m_regionCluts->isEmpty()) { - Q_ASSERT(m_windowRegions.isEmpty()); - kDebug(1212) << "setting up region color correction textures"; - - // Generate region textures (and place them inside a map) - RegionalClutMap::const_iterator rcit; - QMap::const_iterator rit; - for (rcit = m_regionCluts->begin(); rcit != m_regionCluts->end(); ++rcit) { - GLuint tex; - glGenTextures(1, &tex); - setupCCTexture(tex, rcit->c); - - // Insert the new texture into the region maps - rit = m_windowRegions.insert(rcit.key(), rcit->r); // this one maps Window -> QRect - m_regionCCTextures.insert(&(*rit), tex); // this one maps QRect* -> texture - } - } - // TODO Handle errors (what if a texture isn't generated?) } @@ -647,13 +589,6 @@ void ColorCorrectionPrivate::deleteCCTextures() glDeleteTextures(m_outputCCTextures.size(), m_outputCCTextures.data()); m_outputCCTextures.clear(); } - if (!m_regionCCTextures.isEmpty()) { - QMap::const_iterator it; - for (it = m_regionCCTextures.begin(); it != m_regionCCTextures.end(); ++it) - glDeleteTextures(1, &(*it)); - m_regionCCTextures.clear(); - m_windowRegions.clear(); - } } void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) diff --git a/libkwineffects/kwinglcolorcorrection.h b/libkwineffects/kwinglcolorcorrection.h index ee2497f21d..0c7e66b01f 100644 --- a/libkwineffects/kwinglcolorcorrection.h +++ b/libkwineffects/kwinglcolorcorrection.h @@ -51,52 +51,12 @@ public: static ColorCorrection *instance(); static void cleanup(); - /** - * The beginning of a region list for a window \param w - * \return Constant iterator to the beginning - * \see setupForRegion - * - * It can be used to indicate a particular region for which - * to set up color correction. - * - * These regions come from the applications, which communicate with the - * color server (kolor-server in kolor-manager), and this has no direct - * relation to KWin. Consequently, modifying these regions does not - * make sense inside KWin. - */ - QMap::const_iterator regionsBegin(Window w); - - /** - * The ending of a region list for a window \param w - * \return Constant iterator to the ending - * \see setupForRegion - */ - QMap::const_iterator regionsEnd(Window w); - /** * Prepares color correction for the output number \param screen. * Sets up the appropriate color lookup texture for the output. */ void setupForOutput(int screen); - /** - * Prepares color correction for one region of a window (in fact a rect), - * which is indicated by \param regionIt. This can be obtained by iterating - * between \ref regionsBegin and \ref regionsEnd, for that particular window. - * - * \note This should be called when drawing a window - */ - void setupForRegion(const QMap::const_iterator ®ionIt); - - /** - * Disables color correction for a particular window region. Instead, - * color correction is set up again for the last output that was set - * with \ref setupForOutput. - * - * \note This should be called after finishing the drawing of a window. - */ - void resetForRegion(); - /** * Unsets color correction by using a dummy color lookup texture. This * does not disable anything, the CC mechanisms remain in place. Instead, it diff --git a/libkwineffects/kwinglcolorcorrection_p.h b/libkwineffects/kwinglcolorcorrection_p.h index e244d01035..65269df188 100644 --- a/libkwineffects/kwinglcolorcorrection_p.h +++ b/libkwineffects/kwinglcolorcorrection_p.h @@ -96,9 +96,6 @@ public: ColorServerInterface *m_csi; const ClutList *m_outputCluts; QVector m_outputCCTextures; - const RegionalClutMap *m_regionCluts; - QMultiMap m_windowRegions; - QMap m_regionCCTextures; // keys from m_regions's values Clut m_dummyClut; GLuint m_dummyCCTexture; From 1fbb413dafbd2956c33fbd5a93cbd4fdf1549fe4 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 15:53:40 +0300 Subject: [PATCH 08/20] CC: Tweak lanczos filter member --- scene.h | 2 -- scene_opengl.cpp | 10 +++++----- scene_opengl.h | 3 +++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scene.h b/scene.h index feb91c7483..032cebcd6d 100644 --- a/scene.h +++ b/scene.h @@ -32,7 +32,6 @@ class Workspace; class Deleted; class EffectFrameImpl; class EffectWindowImpl; -class LanczosFilter; class OverlayWindow; class Shadow; @@ -154,7 +153,6 @@ protected: QElapsedTimer last_time; Workspace* wspace; bool has_waitSync; - QWeakPointer lanczos_filter; OverlayWindow* m_overlayWindow; }; diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 668453a1d7..ce4806b2f1 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -229,13 +229,13 @@ void SceneOpenGL::finalDrawWindow(EffectWindowImpl* w, int mask, QRegion region, void SceneOpenGL::performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data) { if (mask & PAINT_WINDOW_LANCZOS) { - if (lanczos_filter.isNull()) { - lanczos_filter = new LanczosFilter(this); + if (m_lanczosFilter.isNull()) { + m_lanczosFilter = new LanczosFilter(this); // recreate the lanczos filter when the screen gets resized - connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), lanczos_filter.data(), SLOT(deleteLater())); - connect(QApplication::desktop(), SIGNAL(resized(int)), lanczos_filter.data(), SLOT(deleteLater())); + connect(QApplication::desktop(), SIGNAL(screenCountChanged(int)), m_lanczosFilter.data(), SLOT(deleteLater())); + connect(QApplication::desktop(), SIGNAL(resized(int)), m_lanczosFilter.data(), SLOT(deleteLater())); } - lanczos_filter.data()->performPaint(w, mask, region, data); + m_lanczosFilter.data()->performPaint(w, mask, region, data); } else w->sceneWindow()->performPaint(mask, region, data); } diff --git a/scene_opengl.h b/scene_opengl.h index b92f40f013..45e5e29507 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -31,6 +31,8 @@ along with this program. If not, see . namespace KWin { +class LanczosFilter; + class SceneOpenGL : public Scene { @@ -108,6 +110,7 @@ private: QElapsedTimer m_renderTimer; QRegion m_lastDamage; int m_lastMask; + QWeakPointer m_lanczosFilter; }; class SceneOpenGL::TexturePrivate From 005ab28ad68bd3830443351e9b3cfaf9b3bb47cb Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 17:00:29 +0300 Subject: [PATCH 09/20] CC: No singleton for ColorCorrection --- composite.cpp | 7 ------- libkwineffects/kwinglcolorcorrection.cpp | 25 +++--------------------- libkwineffects/kwinglcolorcorrection.h | 16 ++++----------- libkwineffects/kwinglutils.cpp | 6 ++++-- libkwineffects/kwinglutils.h | 3 +++ scene_opengl.cpp | 23 ++++++++++++++++------ scene_opengl.h | 8 +++++++- scene_opengl_egl.cpp | 2 ++ scene_opengl_glx.cpp | 3 +++ 9 files changed, 43 insertions(+), 50 deletions(-) diff --git a/composite.cpp b/composite.cpp index 57e0df5090..c65716b5ca 100644 --- a/composite.cpp +++ b/composite.cpp @@ -55,8 +55,6 @@ along with this program. If not, see . #include "compositingprefs.h" #include "notifications.h" -#include - #include #include @@ -142,10 +140,6 @@ void Workspace::slotCompositingOptionsInitialized() } #endif - kDebug(1212) << "Color correction:" << options->isColorCorrected(); - ColorCorrection::instance()->setEnabled(options->isColorCorrected()); - connect(ColorCorrection::instance(), SIGNAL(changed()), this, SLOT(addRepaintFull())); - scene = new SceneOpenGL(this); // TODO: Add 30 second delay to protect against screen freezes as well @@ -210,7 +204,6 @@ void Workspace::finishCompositing() if (scene == NULL) return; m_finishingCompositing = true; - ColorCorrection::cleanup(); delete cm_selection; foreach (Client * c, clients) scene->windowClosed(c, NULL); diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index a274827172..a3b6a0e3ff 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -221,23 +221,8 @@ static const char s_ccAlteration[] = * Color Correction */ -ColorCorrection *ColorCorrection::s_colorCorrection = NULL; - -ColorCorrection *ColorCorrection::instance() -{ - if (!s_colorCorrection) - s_colorCorrection = new ColorCorrection; - return s_colorCorrection; -} - -void ColorCorrection::cleanup() -{ - delete s_colorCorrection; - s_colorCorrection = NULL; -} - -ColorCorrection::ColorCorrection() - : QObject() +ColorCorrection::ColorCorrection(QObject *parent) + : QObject(parent) , d_ptr(new ColorCorrectionPrivate(this)) { @@ -305,6 +290,7 @@ void ColorCorrection::setEnabled(bool enabled) #endif d->m_enabled = enabled; + GLShader::sColorCorrect = enabled; kDebug(1212) << enabled; } @@ -357,11 +343,6 @@ void ColorCorrection::reset() QByteArray ColorCorrection::prepareFragmentShader(const QByteArray &sourceCode) { - Q_D(ColorCorrection); - - if (!d->m_enabled) - return sourceCode; - bool sourceIsValid = true; /* diff --git a/libkwineffects/kwinglcolorcorrection.h b/libkwineffects/kwinglcolorcorrection.h index 0c7e66b01f..ec080c0239 100644 --- a/libkwineffects/kwinglcolorcorrection.h +++ b/libkwineffects/kwinglcolorcorrection.h @@ -48,8 +48,8 @@ class KWIN_EXPORT ColorCorrection : public QObject Q_OBJECT public: - static ColorCorrection *instance(); - static void cleanup(); + explicit ColorCorrection(QObject *parent = 0); + virtual ~ColorCorrection(); /** * Prepares color correction for the output number \param screen. @@ -65,14 +65,11 @@ public: void reset(); /** - * When color correction is disabled, it does nothing and returns - * \param sourceCode. - * - * Else, it modifies \param sourceCode, making it suitable for performing + * Modifies \param sourceCode, making it suitable for performing * color correction. This is done by inserting a 3d texture lookup operation * just before the output fragment color is returned. */ - QByteArray prepareFragmentShader(const QByteArray &sourceCode); + static QByteArray prepareFragmentShader(const QByteArray &sourceCode); public slots: /** @@ -88,14 +85,9 @@ signals: */ void changed(); -private: - ColorCorrection(); - virtual ~ColorCorrection(); - private: ColorCorrectionPrivate * const d_ptr; Q_DECLARE_PRIVATE(ColorCorrection) - static ColorCorrection *s_colorCorrection; }; } // KWin namespace diff --git a/libkwineffects/kwinglutils.cpp b/libkwineffects/kwinglutils.cpp index edddc0d6a1..b4495c5dac 100644 --- a/libkwineffects/kwinglutils.cpp +++ b/libkwineffects/kwinglutils.cpp @@ -264,6 +264,8 @@ void popMatrix() // GLShader //**************************************** +bool GLShader::sColorCorrect = false; + GLShader::GLShader() : mProgram(0) , mValid(false) @@ -318,8 +320,8 @@ const QByteArray GLShader::prepareSource(GLenum shaderType, const QByteArray &so ba.append(source); // Inject color correction code for fragment shaders, if possible - if (shaderType == GL_FRAGMENT_SHADER) - ba = ColorCorrection::instance()->prepareFragmentShader(ba); + if (shaderType == GL_FRAGMENT_SHADER && sColorCorrect) + ba = ColorCorrection::prepareFragmentShader(ba); return ba; } diff --git a/libkwineffects/kwinglutils.h b/libkwineffects/kwinglutils.h index 7f092a5772..42120d775b 100644 --- a/libkwineffects/kwinglutils.h +++ b/libkwineffects/kwinglutils.h @@ -220,6 +220,9 @@ private: int mFloatLocation[FloatUniformCount]; int mIntLocation[IntUniformCount]; + static bool sColorCorrect; + + friend class ColorCorrection; friend class ShaderManager; }; diff --git a/scene_opengl.cpp b/scene_opengl.cpp index ce4806b2f1..8682c0f8f0 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -122,6 +122,18 @@ bool SceneOpenGL::initFailed() const return !init_ok; } +ColorCorrection* SceneOpenGL::colorCorrection() +{ + return m_colorCorrection; +} + +void SceneOpenGL::initColorCorrection() +{ + kDebug(1212) << "Color correction:" << options->isColorCorrected(); + m_colorCorrection->setEnabled(options->isColorCorrected()); + connect(m_colorCorrection, SIGNAL(changed()), wspace, SLOT(addRepaintFull())); +} + bool SceneOpenGL::selectMode() { if (!initDrawableConfigs()) @@ -243,7 +255,7 @@ void SceneOpenGL::performPaintWindow(EffectWindowImpl* w, int mask, QRegion regi void SceneOpenGL::windowAdded(Toplevel* c) { assert(!windows.contains(c)); - windows[ c ] = new Window(c); + windows[ c ] = new Window(c, this); connect(c, SIGNAL(opacityChanged(KWin::Toplevel*,qreal)), SLOT(windowOpacityChanged(KWin::Toplevel*))); connect(c, SIGNAL(geometryShapeChanged(KWin::Toplevel*,QRect)), SLOT(windowGeometryShapeChanged(KWin::Toplevel*))); connect(c, SIGNAL(windowClosed(KWin::Toplevel*,KWin::Deleted*)), SLOT(windowClosed(KWin::Toplevel*,KWin::Deleted*))); @@ -375,7 +387,7 @@ bool SceneOpenGL::Texture::load(const QPixmap& pixmap, GLenum target) // SceneOpenGL::Window //**************************************** -SceneOpenGL::Window::Window(Toplevel* c) +SceneOpenGL::Window::Window(Toplevel* c, SceneOpenGL* scene) : Scene::Window(c) , texture() , topTexture() @@ -383,6 +395,7 @@ SceneOpenGL::Window::Window(Toplevel* c) , rightTexture() , bottomTexture() { + m_scene = scene; } SceneOpenGL::Window::~Window() @@ -524,8 +537,7 @@ void SceneOpenGL::Window::performPaint(int mask, QRegion region, WindowPaintData data.shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); data.shader->setUniform(GLShader::Offset, QVector2D(x(), y())); } - if (options->isColorCorrected()) - ColorCorrection::instance()->setupForOutput(data.screen()); + m_scene->colorCorrection()->setupForOutput(data.screen()); sceneShader = true; } @@ -883,8 +895,7 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa shader->setUniform(GLShader::Saturation, saturation); shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0); - if (options->isColorCorrected()) - ColorCorrection::instance()->setupForOutput(screen); + m_scene->colorCorrection()->setupForOutput(screen); } void SceneOpenGL::Window::prepareRenderStates(TextureType type, double opacity, double brightness, double saturation, int screen, GLTexture *tex) diff --git a/scene_opengl.h b/scene_opengl.h index 45e5e29507..e482269baa 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -31,6 +31,7 @@ along with this program. If not, see . namespace KWin { +class ColorCorrection; class LanczosFilter; class SceneOpenGL @@ -55,6 +56,8 @@ public: void idle(); + ColorCorrection *colorCorrection(); + protected: virtual void paintGenericScreen(int mask, ScreenPaintData data); virtual void paintBackground(QRegion region); @@ -71,6 +74,7 @@ private: bool initRenderingContext(); bool initBufferConfigs(); bool initDrawableConfigs(); + void initColorCorrection(); void waitSync(); #ifndef KWIN_HAVE_OPENGLES void setupModelViewProjectionMatrix(); @@ -111,6 +115,7 @@ private: QRegion m_lastDamage; int m_lastMask; QWeakPointer m_lanczosFilter; + ColorCorrection *m_colorCorrection; }; class SceneOpenGL::TexturePrivate @@ -166,7 +171,7 @@ class SceneOpenGL::Window : public Scene::Window { public: - Window(Toplevel* c); + Window(Toplevel* c, SceneOpenGL* scene); virtual ~Window(); virtual void performPaint(int mask, QRegion region, WindowPaintData data); virtual void pixmapDiscarded(); @@ -204,6 +209,7 @@ private: Texture leftTexture; Texture rightTexture; Texture bottomTexture; + SceneOpenGL *m_scene; }; class SceneOpenGL::EffectFrame diff --git a/scene_opengl_egl.cpp b/scene_opengl_egl.cpp index 33e8960413..2803c5f519 100644 --- a/scene_opengl_egl.cpp +++ b/scene_opengl_egl.cpp @@ -31,6 +31,7 @@ int surfaceHasSubPost; SceneOpenGL::SceneOpenGL(Workspace* ws) : Scene(ws) , init_ok(false) + , m_colorCorrection(new ColorCorrection(this)) { if (!initRenderingContext()) return; @@ -51,6 +52,7 @@ SceneOpenGL::SceneOpenGL(Workspace* ws) return; } debug = qstrcmp(qgetenv("KWIN_GL_DEBUG"), "1") == 0; + initColorCorrection(); if (!ShaderManager::instance()->isValid()) { kError(1212) << "Shaders not valid, ES compositing not possible"; return; diff --git a/scene_opengl_glx.cpp b/scene_opengl_glx.cpp index e0654b5861..0b774360e8 100644 --- a/scene_opengl_glx.cpp +++ b/scene_opengl_glx.cpp @@ -39,6 +39,7 @@ SceneOpenGL::SceneOpenGL(Workspace* ws) : Scene(ws) , m_resetModelViewProjectionMatrix(true) , init_ok(false) + , m_colorCorrection(new ColorCorrection(this)) { initGLX(); // check for FBConfig support @@ -102,6 +103,8 @@ SceneOpenGL::SceneOpenGL(Workspace* ws) debug = qstrcmp(qgetenv("KWIN_GL_DEBUG"), "1") == 0; + initColorCorrection(); + // scene shader setup if (GLPlatform::instance()->supports(GLSL)) { if (!ShaderManager::instance()->isValid()) { From c2bed6d20e5969a25445752174553092d58b358f Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 17:30:13 +0300 Subject: [PATCH 10/20] CC: Fix texture clamp issues --- libkwineffects/kwinglcolorcorrection.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index a3b6a0e3ff..2600492e2d 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -214,7 +214,7 @@ void ColorServerInterface::callFinishedSlot(QDBusPendingCallWatcher *watcher) static const char s_ccVars[] = "uniform sampler3D u_ccLookupTexture;\n"; static const char s_ccAlteration[] = - "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb * 63.0 / 64.0).rgb;\n"; + "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb).rgb;\n"; /* @@ -585,9 +585,9 @@ void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, texture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); From 7742e9d85261ff27aa44ea716d4a06cb16249676 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 17:35:05 +0300 Subject: [PATCH 11/20] CC: Remove useless enabling and disabling for gl_texture_3d --- libkwineffects/kwinglcolorcorrection.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index 2600492e2d..1d7f2a488d 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -317,7 +317,6 @@ void ColorCorrection::setupForOutput(int screen) GLint activeTexture; glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); glActiveTexture(GL_TEXTURE0 + d->m_ccTextureUnit); - glEnable(GL_TEXTURE_3D); if (screen < 0 || screen >= d->m_outputCCTextures.count()) { // Configure with a dummy texture in case something is wrong @@ -582,7 +581,6 @@ void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) kDebug(1212) << texture; #ifndef KWIN_HAVE_OPENGLES - glEnable(GL_TEXTURE_3D); glBindTexture(GL_TEXTURE_3D, texture); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -595,7 +593,6 @@ void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) LUT_GRID_POINTS, LUT_GRID_POINTS, LUT_GRID_POINTS, 0, GL_RGB, GL_UNSIGNED_SHORT, clut.data()); - glDisable(GL_TEXTURE_3D); checkGLError("setupCCTexture"); #else From 6f18533b9c03ea7159da83db16d3fdc1df20f7d2 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Mon, 27 Aug 2012 17:35:25 +0300 Subject: [PATCH 12/20] CC: Remove useless check for minimum number of texture units --- libkwineffects/kwinglcolorcorrection.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index 1d7f2a488d..0f4b3af6d5 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -522,16 +522,6 @@ void ColorCorrectionPrivate::setupCCTextures() if (m_ccTextureUnit < 0) { GLint maxUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxUnits); - - if (maxUnits < 2) { - kWarning(1212) << "insufficient maximum number of texture units allowed:" << maxUnits; - kWarning(1212) << "color correction will be disabled"; - m_hasError = true; - m_ccTextureUnit = 0; - q->setEnabled(false); - return; - } - m_ccTextureUnit = maxUnits - 1; } From f211961064dc491ec0907660c183d14c3fde64d8 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Tue, 4 Sep 2012 21:55:37 +0300 Subject: [PATCH 13/20] CC: Fix premultiplied alpha issue --- libkwineffects/kwinglcolorcorrection.cpp | 2 +- scene-fragment.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index 0f4b3af6d5..35b63c470e 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -214,7 +214,7 @@ void ColorServerInterface::callFinishedSlot(QDBusPendingCallWatcher *watcher) static const char s_ccVars[] = "uniform sampler3D u_ccLookupTexture;\n"; static const char s_ccAlteration[] = - "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb).rgb;\n"; + "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb / gl_FragColor.a).rgb;\n"; /* diff --git a/scene-fragment.glsl b/scene-fragment.glsl index 4b5424be16..cf0a87ae10 100644 --- a/scene-fragment.glsl +++ b/scene-fragment.glsl @@ -10,7 +10,7 @@ varying vec2 varyingTexCoords; void main() { vec4 tex = texture2D(sampler, varyingTexCoords); - tex.a += float(u_forceAlpha); + tex.a = min(tex.a + float(u_forceAlpha), 1.0); if (saturation != 1.0) { tex.rgb = mix(vec3(dot( vec3( 0.30, 0.59, 0.11 ), tex.rgb )), tex.rgb, saturation); From 5247c56f5eb269c1d5d6cafe10ff5cdea5897353 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Tue, 4 Sep 2012 22:01:07 +0300 Subject: [PATCH 14/20] CC: Fix unused variable warning --- libkwineffects/kwinglcolorcorrection.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index 35b63c470e..c0dcabd911 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -517,8 +517,6 @@ QByteArray ColorCorrection::prepareFragmentShader(const QByteArray &sourceCode) void ColorCorrectionPrivate::setupCCTextures() { - Q_Q(ColorCorrection); - if (m_ccTextureUnit < 0) { GLint maxUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxUnits); From 8bec3fda713d57c4ab847902cf0388e0465a717e Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 16 Sep 2012 14:29:06 +0300 Subject: [PATCH 15/20] CC: Fix color correction init signal connections --- scene_opengl.cpp | 4 +++- workspace.cpp | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 54d3473851..8f63d6867c 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -75,6 +75,7 @@ Sources and other compositing managers: #include "utils.h" #include "client.h" +#include "composite.h" #include "deleted.h" #include "effects.h" #include "lanczosfilter.h" @@ -131,7 +132,8 @@ void SceneOpenGL::initColorCorrection() { kDebug(1212) << "Color correction:" << options->isColorCorrected(); m_colorCorrection->setEnabled(options->isColorCorrected()); - connect(m_colorCorrection, SIGNAL(changed()), wspace, SLOT(addRepaintFull())); + connect(m_colorCorrection, SIGNAL(changed()), Compositor::self(), SLOT(addRepaintFull())); + connect(options, SIGNAL(colorCorrectedChanged()), Compositor::self(), SLOT(slotReinitialize())); } bool SceneOpenGL::selectMode() diff --git a/workspace.cpp b/workspace.cpp index 3733af01cf..258a237534 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -201,7 +201,6 @@ Workspace::Workspace(bool restore) m_compositor = Compositor::createCompositor(this); connect(this, SIGNAL(currentDesktopChanged(int,KWin::Client*)), m_compositor, SLOT(addRepaintFull())); connect(m_compositor, SIGNAL(compositingToggled(bool)), SLOT(slotCompositingToggled())); - connect(options, SIGNAL(glColorCorrectionChanged()), m_compositor, SLOT(resetCompositing())); new DBusInterface(this); From ba4cd7841964ae13010cd23b10034ee680992d9b Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 16 Sep 2012 16:28:52 +0300 Subject: [PATCH 16/20] CC: Redo init and uninit, try to avoid fatal IO errors Additional checks for GL errors. Attempt to fix transparency issues again. --- libkwineffects/kwinglcolorcorrection.cpp | 15 ++++++++----- scene_opengl.cpp | 28 +++++++++++++++++++----- scene_opengl.h | 3 +++ scene_opengl_egl.cpp | 3 ++- scene_opengl_glx.cpp | 3 ++- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index c0dcabd911..e0ea2dd84b 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -214,7 +214,7 @@ void ColorServerInterface::callFinishedSlot(QDBusPendingCallWatcher *watcher) static const char s_ccVars[] = "uniform sampler3D u_ccLookupTexture;\n"; static const char s_ccAlteration[] = - "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb / gl_FragColor.a).rgb;\n"; + "gl_FragColor.rgb = texture3D(u_ccLookupTexture, gl_FragColor.rgb / min(gl_FragColor.a, 1.0)).rgb;\n"; /* @@ -298,9 +298,6 @@ void ColorCorrection::setupForOutput(int screen) { Q_D(ColorCorrection); - if (!d->m_enabled) - return; - GLShader *shader = ShaderManager::instance()->getBoundShader(); if (!shader) { kError(1212) << "no bound shader for color correction setup"; @@ -308,6 +305,9 @@ void ColorCorrection::setupForOutput(int screen) } if (!shader->setUniform("u_ccLookupTexture", d->m_ccTextureUnit)) { + // This means the color correction shaders are probably not loaded + if (!d->m_enabled) + return; kError(1212) << "unable to set uniform for the color correction lookup texture"; } @@ -318,7 +318,7 @@ void ColorCorrection::setupForOutput(int screen) glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); glActiveTexture(GL_TEXTURE0 + d->m_ccTextureUnit); - if (screen < 0 || screen >= d->m_outputCCTextures.count()) { + if (d->m_outputCCTextures.isEmpty() || screen < 0 || screen >= d->m_outputCCTextures.count()) { // Configure with a dummy texture in case something is wrong Q_ASSERT(d->m_dummyCCTexture != 0); glBindTexture(GL_TEXTURE_3D, d->m_dummyCCTexture); @@ -332,6 +332,8 @@ void ColorCorrection::setupForOutput(int screen) Q_UNUSED(screen); #endif // KWIN_HAVE_OPENGLES + checkGLError("setupForOutput"); + d->m_lastOutput = screen; } @@ -542,6 +544,7 @@ void ColorCorrectionPrivate::setupCCTextures() } // TODO Handle errors (what if a texture isn't generated?) + checkGLError("setupCCTextures"); } void ColorCorrectionPrivate::deleteCCTextures() @@ -557,6 +560,8 @@ void ColorCorrectionPrivate::deleteCCTextures() glDeleteTextures(m_outputCCTextures.size(), m_outputCCTextures.data()); m_outputCCTextures.clear(); } + + checkGLError("deleteCCTextures"); } void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 8f63d6867c..48537cfd05 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -131,9 +131,25 @@ ColorCorrection* SceneOpenGL::colorCorrection() void SceneOpenGL::initColorCorrection() { kDebug(1212) << "Color correction:" << options->isColorCorrected(); + m_colorCorrection = new ColorCorrection(this); m_colorCorrection->setEnabled(options->isColorCorrected()); connect(m_colorCorrection, SIGNAL(changed()), Compositor::self(), SLOT(addRepaintFull())); - connect(options, SIGNAL(colorCorrectedChanged()), Compositor::self(), SLOT(slotReinitialize())); + connect(options, SIGNAL(colorCorrectedChanged()), this, SLOT(slotColorCorrectedChanged())); +} + +void SceneOpenGL::slotColorCorrectedChanged() +{ + m_colorCorrection->setEnabled(options->isColorCorrected()); + + // Reload all shaders + ShaderManager::cleanup(); + ShaderManager::instance(); +} + +void SceneOpenGL::uninitColorCorrection() +{ + kDebug(1212); + disconnect(options, SIGNAL(colorCorrectedChanged()), Compositor::self(), SLOT(slotReinitialize())); } bool SceneOpenGL::selectMode() @@ -881,15 +897,15 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa opaque = false; if (!opaque) { glEnable(GL_BLEND); - if (!options->isColorCorrected()) { +// if (!options->isColorCorrected()) { if (alpha) { - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else { glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity); - glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); } - } else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// } else +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } const float rgb = brightness * opacity; diff --git a/scene_opengl.h b/scene_opengl.h index b3fce2c219..13bf2a5f68 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -68,6 +68,8 @@ public Q_SLOTS: virtual void windowOpacityChanged(KWin::Toplevel* c); virtual void windowGeometryShapeChanged(KWin::Toplevel* c); virtual void windowClosed(KWin::Toplevel* c, KWin::Deleted* deleted); +private Q_SLOTS: + void slotColorCorrectedChanged(); private: bool selectMode(); bool initTfp(); @@ -76,6 +78,7 @@ private: bool initBufferConfigs(); bool initDrawableConfigs(); void initColorCorrection(); + void uninitColorCorrection(); void waitSync(); #ifndef KWIN_HAVE_OPENGLES void setupModelViewProjectionMatrix(); diff --git a/scene_opengl_egl.cpp b/scene_opengl_egl.cpp index d11c59cd62..c82a76189f 100644 --- a/scene_opengl_egl.cpp +++ b/scene_opengl_egl.cpp @@ -31,7 +31,7 @@ int surfaceHasSubPost; SceneOpenGL::SceneOpenGL(Workspace* ws) : Scene(ws) , init_ok(false) - , m_colorCorrection(new ColorCorrection(this)) + , m_colorCorrection(NULL) { if (!initRenderingContext()) return; @@ -97,6 +97,7 @@ SceneOpenGL::~SceneOpenGL() eglTerminate(dpy); eglReleaseThread(); SceneOpenGL::EffectFrame::cleanup(); + uninitColorCorrection(); checkGLError("Cleanup"); if (m_overlayWindow->window()) { m_overlayWindow->destroy(); diff --git a/scene_opengl_glx.cpp b/scene_opengl_glx.cpp index 9f2ef0794b..36747cc44e 100644 --- a/scene_opengl_glx.cpp +++ b/scene_opengl_glx.cpp @@ -39,7 +39,7 @@ SceneOpenGL::SceneOpenGL(Workspace* ws) : Scene(ws) , m_resetModelViewProjectionMatrix(true) , init_ok(false) - , m_colorCorrection(new ColorCorrection(this)) + , m_colorCorrection(NULL) { initGLX(); // check for FBConfig support @@ -155,6 +155,7 @@ SceneOpenGL::~SceneOpenGL() XFreePixmap(display(), buffer); } SceneOpenGL::EffectFrame::cleanup(); + uninitColorCorrection(); checkGLError("Cleanup"); } From 2dcf424d633873956e3b590c8d42818217f79b1b Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 23 Sep 2012 12:40:20 +0300 Subject: [PATCH 17/20] CC: Enable cc with OpenGL ES >= 3 (should support 3d textures) --- libkwineffects/kwinglcolorcorrection.cpp | 40 +++++++++++++++--------- libkwineffects/kwinglplatform.cpp | 9 ++++++ libkwineffects/kwinglplatform.h | 4 +++ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/libkwineffects/kwinglcolorcorrection.cpp b/libkwineffects/kwinglcolorcorrection.cpp index e0ea2dd84b..48f2e3462e 100644 --- a/libkwineffects/kwinglcolorcorrection.cpp +++ b/libkwineffects/kwinglcolorcorrection.cpp @@ -21,6 +21,7 @@ along with this program. If not, see . #include "kwinglcolorcorrection.h" #include "kwinglcolorcorrection_p.h" +#include "kwinglplatform.h" #include "kwinglutils.h" #include @@ -33,6 +34,26 @@ along with this program. If not, see . #include #include +#ifdef KWIN_HAVE_OPENGLES +#define CC_TEXTURE_INTERNAL_FORMAT GL_RGB + +/* + * A bit of ugliness to allow building with OpenGL ES < 3, without + * ifdef's everywhere in the code. These should not actually be used anywhere. + */ +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F // From OES_texture_3D extension +#define GL_TEXTURE_WRAP_R 0x8072 // From OES_texture_3D extension +void glTexImage3D(GLenum, int, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *) +{ + Q_ASSERT(false); // Execution must not reach here +} +#endif // defined(GL_TEXTURE_3D) + +#else // KWIN_HAVE_OPENGLES +#define CC_TEXTURE_INTERNAL_FORMAT GL_RGB16 +#endif // KWIN_HAVE_OPENGLES + namespace KWin { @@ -275,19 +296,18 @@ void ColorCorrection::setEnabled(bool enabled) return; } -#ifdef KWIN_HAVE_OPENGLES - if (enabled) { - kWarning(1212) << "color correction is not supported with OpenGL ES at the moment."; + const GLPlatform *gl = GLPlatform::instance(); + if (enabled && gl->isGLES() && (gl->glVersion() >> 32) < 3) { + kError(1212) << "color correction is not supported with OpenGL ES < 3.0"; return; } -#else + if (enabled) { // Update all profiles and regions d->m_csi->update(); } else { d->deleteCCTextures(); } -#endif d->m_enabled = enabled; GLShader::sColorCorrect = enabled; @@ -311,7 +331,6 @@ void ColorCorrection::setupForOutput(int screen) kError(1212) << "unable to set uniform for the color correction lookup texture"; } -#ifndef KWIN_HAVE_OPENGLES d->setupCCTextures(); GLint activeTexture; @@ -328,9 +347,6 @@ void ColorCorrection::setupForOutput(int screen) } glActiveTexture(activeTexture); -#else - Q_UNUSED(screen); -#endif // KWIN_HAVE_OPENGLES checkGLError("setupForOutput"); @@ -573,7 +589,6 @@ void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) kDebug(1212) << texture; -#ifndef KWIN_HAVE_OPENGLES glBindTexture(GL_TEXTURE_3D, texture); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -582,15 +597,12 @@ void ColorCorrectionPrivate::setupCCTexture(GLuint texture, const Clut& clut) glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16, + glTexImage3D(GL_TEXTURE_3D, 0, CC_TEXTURE_INTERNAL_FORMAT, LUT_GRID_POINTS, LUT_GRID_POINTS, LUT_GRID_POINTS, 0, GL_RGB, GL_UNSIGNED_SHORT, clut.data()); checkGLError("setupCCTexture"); -#else - Q_UNUSED(texture); -#endif // KWIN_HAVE_OPENGLES } void ColorCorrectionPrivate::colorServerUpdateSucceededSlot() diff --git a/libkwineffects/kwinglplatform.cpp b/libkwineffects/kwinglplatform.cpp index 26341e4d8b..2e97a9b057 100644 --- a/libkwineffects/kwinglplatform.cpp +++ b/libkwineffects/kwinglplatform.cpp @@ -919,5 +919,14 @@ bool GLPlatform::isLooseBinding() const return m_looseBinding; } +bool GLPlatform::isGLES() const +{ +#ifdef KWIN_HAVE_OPENGLES + return true; +#else + return false; +#endif +} + } // namespace KWin diff --git a/libkwineffects/kwinglplatform.h b/libkwineffects/kwinglplatform.h index 14555a2bd4..350ea09b71 100644 --- a/libkwineffects/kwinglplatform.h +++ b/libkwineffects/kwinglplatform.h @@ -272,6 +272,10 @@ public: * @since 4.9 **/ bool isLooseBinding() const; + /** + * @returns Whether OpenGL ES is used + */ + bool isGLES() const; /** * @returns a human readable form of the @p version. From b17071555dae3c063ac05d4a60c141a0a4169b68 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 23 Sep 2012 15:32:24 +0300 Subject: [PATCH 18/20] CC: Fix blend function, it's different for cc enabled --- scene_opengl.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 457b107d32..84c32c570a 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -1247,15 +1247,16 @@ void SceneOpenGL2Window::prepareStates(TextureType type, qreal opacity, qreal br opaque = false; if (!opaque) { glEnable(GL_BLEND); -// if (!options->isColorCorrected()) { + if (options->isColorCorrected()) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } else { if (alpha) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { glBlendColor((float)opacity, (float)opacity, (float)opacity, (float)opacity); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); } -// } else -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } } const qreal rgb = brightness * opacity; From f219c108bbf1f6acdf2217b1379e83bf54192e3c Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 23 Sep 2012 15:32:58 +0300 Subject: [PATCH 19/20] CC: Remove unnecessary init/uninit CC methods --- scene_opengl.cpp | 24 ++++++------------------ scene_opengl.h | 2 -- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 84c32c570a..2d42c2d70e 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -429,9 +429,13 @@ bool SceneOpenGL2::supported(OpenGLBackend *backend) SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend) : SceneOpenGL(Workspace::self(), backend) - , m_colorCorrection(NULL) + , m_colorCorrection(new ColorCorrection(this)) { - initColorCorrection(); // NOTE is this the right place? + // Initialize color correction before the shaders + kDebug(1212) << "Color correction:" << options->isColorCorrected(); + m_colorCorrection->setEnabled(options->isColorCorrected()); + connect(m_colorCorrection, SIGNAL(changed()), Compositor::self(), SLOT(addRepaintFull())); + connect(options, SIGNAL(colorCorrectedChanged()), this, SLOT(slotColorCorrectedChanged())); if (!ShaderManager::instance()->isValid()) { kDebug(1212) << "No Scene Shaders available"; @@ -451,7 +455,6 @@ SceneOpenGL2::SceneOpenGL2(OpenGLBackend *backend) SceneOpenGL2::~SceneOpenGL2() { - uninitColorCorrection(); } void SceneOpenGL2::paintGenericScreen(int mask, ScreenPaintData data) @@ -523,15 +526,6 @@ ColorCorrection *SceneOpenGL2::colorCorrection() return m_colorCorrection; } -void SceneOpenGL2::initColorCorrection() -{ - kDebug(1212) << "Color correction:" << options->isColorCorrected(); - m_colorCorrection = new ColorCorrection(this); - m_colorCorrection->setEnabled(options->isColorCorrected()); - connect(m_colorCorrection, SIGNAL(changed()), Compositor::self(), SLOT(addRepaintFull())); - connect(options, SIGNAL(colorCorrectedChanged()), this, SLOT(slotColorCorrectedChanged())); -} - void SceneOpenGL2::slotColorCorrectedChanged() { m_colorCorrection->setEnabled(options->isColorCorrected()); @@ -541,12 +535,6 @@ void SceneOpenGL2::slotColorCorrectedChanged() ShaderManager::instance(); } -void SceneOpenGL2::uninitColorCorrection() -{ - kDebug(1212); - disconnect(options, SIGNAL(colorCorrectedChanged()), Compositor::self(), SLOT(slotReinitialize())); -} - //**************************************** // SceneOpenGL1 //**************************************** diff --git a/scene_opengl.h b/scene_opengl.h index adeb43e0aa..3ef0baa8cd 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -108,8 +108,6 @@ private Q_SLOTS: void slotColorCorrectedChanged(); private: - void initColorCorrection(); - void uninitColorCorrection(); void performPaintWindow(EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data); private: From e26cc0a4cfa4fc9b48882489db64d25e8ee5fa30 Mon Sep 17 00:00:00 2001 From: Casian Andrei Date: Sun, 23 Sep 2012 15:36:23 +0300 Subject: [PATCH 20/20] CC: Remove a couple of extraneous empty lines --- glxbackend.cpp | 1 - scene_opengl.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/glxbackend.cpp b/glxbackend.cpp index 8675ab8004..cef88d433a 100644 --- a/glxbackend.cpp +++ b/glxbackend.cpp @@ -45,7 +45,6 @@ GlxBackend::GlxBackend() init(); } - GlxBackend::~GlxBackend() { // TODO: cleanup in error case diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 2d42c2d70e..0bf7ce88a6 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -255,7 +255,6 @@ bool SceneOpenGL::initFailed() const return !init_ok; } - int SceneOpenGL::paint(QRegion damage, ToplevelList toplevels) { // actually paint the frame, flushed with the NEXT frame