kwin/plugins/colord-integration/colorddevice.cpp
Vlad Zahorodnii f037a69f1c Introduce colord integration
This change introduces basic colord integration in wayland session. It
is implemented as a binary plugin.

If an output is connected, the plugin will create the corresponding
colord device using the D-Bus API and start monitoring the device for
changes.

When a colord devices changes, the plugin will read the VCGT tag of the
current ICC color profile and apply it.
2020-11-24 17:51:32 +02:00

96 lines
2.9 KiB
C++

/*
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "colorddevice.h"
#include "abstract_output.h"
#include "colordlogging.h"
#include "colordprofileinterface.h"
#include <lcms2.h>
namespace KWin
{
ColordDevice::ColordDevice(AbstractOutput *output, QObject *parent)
: QObject(parent)
, m_output(output)
{
}
AbstractOutput *ColordDevice::output() const
{
return m_output;
}
QDBusObjectPath ColordDevice::objectPath() const
{
return m_colordInterface ? QDBusObjectPath(m_colordInterface->path()) : QDBusObjectPath();
}
void ColordDevice::initialize(const QDBusObjectPath &devicePath)
{
m_colordInterface = new CdDeviceInterface(QStringLiteral("org.freedesktop.ColorManager"),
devicePath.path(), QDBusConnection::systemBus(), this);
connect(m_colordInterface, &CdDeviceInterface::Changed, this, &ColordDevice::updateProfile);
updateProfile();
}
void ColordDevice::updateProfile()
{
const QList<QDBusObjectPath> profiles = m_colordInterface->profiles();
if (profiles.isEmpty()) {
qCDebug(KWIN_COLORD) << m_output->name() << "has no any color profile assigned";
return;
}
CdProfileInterface profile(QStringLiteral("org.freedesktop.ColorManager"),
profiles.first().path(), QDBusConnection::systemBus());
if (!profile.isValid()) {
qCWarning(KWIN_COLORD) << profiles.first() << "is an invalid color profile";
return;
}
cmsHPROFILE handle = cmsOpenProfileFromFile(profile.filename().toUtf8(), "r");
if (!handle) {
qCWarning(KWIN_COLORD) << "Failed to open profile file" << profile.filename();
return;
}
GammaRamp ramp(m_output->gammaRampSize());
uint16_t *redChannel = ramp.red();
uint16_t *greenChannel = ramp.green();
uint16_t *blueChannel = ramp.blue();
cmsToneCurve **vcgt = static_cast<cmsToneCurve **>(cmsReadTag(handle, cmsSigVcgtTag));
if (!vcgt || !vcgt[0]) {
qCDebug(KWIN_COLORD) << "Profile" << profile.filename() << "has no VCGT tag";
for (uint32_t i = 0; i < ramp.size(); ++i) {
const uint16_t value = (i * 0xffff) / (ramp.size() - 1);
redChannel[i] = value;
greenChannel[i] = value;
blueChannel[i] = value;
}
} else {
for (uint32_t i = 0; i < ramp.size(); ++i) {
const uint16_t index = (i * 0xffff) / (ramp.size() - 1);
redChannel[i] = cmsEvalToneCurve16(vcgt[0], index);
greenChannel[i] = cmsEvalToneCurve16(vcgt[1], index);
blueChannel[i] = cmsEvalToneCurve16(vcgt[2], index);
}
}
cmsCloseProfile(handle);
if (!m_output->setGammaRamp(ramp)) {
qCWarning(KWIN_COLORD) << "Failed to apply color profilie on output" << m_output->name();
}
}
} // namespace KWin