File indexing completed on 2024-11-10 04:56:37
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "colordevice.h" 0008 #include "core/colorpipelinestage.h" 0009 #include "core/colortransformation.h" 0010 #include "core/output.h" 0011 #include "utils/common.h" 0012 0013 #include "3rdparty/colortemperature.h" 0014 0015 #include <QTimer> 0016 0017 #include <lcms2.h> 0018 0019 namespace KWin 0020 { 0021 0022 class ColorDevicePrivate 0023 { 0024 public: 0025 void recalculateFactors(); 0026 0027 Output *output; 0028 QTimer *updateTimer; 0029 uint brightness = 100; 0030 uint temperature = 6500; 0031 0032 QVector3D temperatureFactors = QVector3D(1, 1, 1); 0033 QVector3D brightnessFactors = QVector3D(1, 1, 1); 0034 0035 std::shared_ptr<ColorTransformation> transformation; 0036 // used if only limited per-channel multiplication is available 0037 QVector3D simpleTransformation = QVector3D(1, 1, 1); 0038 }; 0039 0040 static qreal interpolate(qreal a, qreal b, qreal blendFactor) 0041 { 0042 return (1 - blendFactor) * a + blendFactor * b; 0043 } 0044 0045 void ColorDevicePrivate::recalculateFactors() 0046 { 0047 brightnessFactors = QVector3D(brightness / 100.0, brightness / 100.0, brightness / 100.0); 0048 0049 if (temperature == 6500) { 0050 temperatureFactors = QVector3D(1, 1, 1); 0051 } else { 0052 // Note that cmsWhitePointFromTemp() returns a slightly green-ish white point. 0053 const int blackBodyColorIndex = ((temperature - 1000) / 100) * 3; 0054 const qreal blendFactor = (temperature % 100) / 100.0; 0055 0056 const qreal xWhitePoint = interpolate(blackbodyColor[blackBodyColorIndex + 0], 0057 blackbodyColor[blackBodyColorIndex + 3], 0058 blendFactor); 0059 const qreal yWhitePoint = interpolate(blackbodyColor[blackBodyColorIndex + 1], 0060 blackbodyColor[blackBodyColorIndex + 4], 0061 blendFactor); 0062 const qreal zWhitePoint = interpolate(blackbodyColor[blackBodyColorIndex + 2], 0063 blackbodyColor[blackBodyColorIndex + 5], 0064 blendFactor); 0065 // the values in the blackbodyColor array are "gamma corrected", but we need a linear value 0066 temperatureFactors = ColorDescription::encodedToNits(QVector3D(xWhitePoint, yWhitePoint, zWhitePoint), NamedTransferFunction::gamma22, 1); 0067 } 0068 simpleTransformation = brightnessFactors * temperatureFactors; 0069 } 0070 0071 ColorDevice::ColorDevice(Output *output, QObject *parent) 0072 : QObject(parent) 0073 , d(new ColorDevicePrivate) 0074 { 0075 d->updateTimer = new QTimer(this); 0076 d->updateTimer->setSingleShot(true); 0077 connect(d->updateTimer, &QTimer::timeout, this, &ColorDevice::update); 0078 0079 d->output = output; 0080 scheduleUpdate(); 0081 } 0082 0083 ColorDevice::~ColorDevice() 0084 { 0085 } 0086 0087 Output *ColorDevice::output() const 0088 { 0089 return d->output; 0090 } 0091 0092 uint ColorDevice::brightness() const 0093 { 0094 return d->brightness; 0095 } 0096 0097 void ColorDevice::setBrightness(uint brightness) 0098 { 0099 if (brightness > 100) { 0100 qCWarning(KWIN_CORE) << "Got invalid brightness value:" << brightness; 0101 brightness = 100; 0102 } 0103 if (d->brightness == brightness) { 0104 return; 0105 } 0106 d->brightness = brightness; 0107 scheduleUpdate(); 0108 Q_EMIT brightnessChanged(); 0109 } 0110 0111 uint ColorDevice::temperature() const 0112 { 0113 return d->temperature; 0114 } 0115 0116 void ColorDevice::setTemperature(uint temperature) 0117 { 0118 if (temperature > 6500) { 0119 qCWarning(KWIN_CORE) << "Got invalid temperature value:" << temperature; 0120 temperature = 6500; 0121 } 0122 if (d->temperature == temperature) { 0123 return; 0124 } 0125 d->temperature = temperature; 0126 scheduleUpdate(); 0127 Q_EMIT temperatureChanged(); 0128 } 0129 0130 void ColorDevice::update() 0131 { 0132 d->recalculateFactors(); 0133 d->output->setChannelFactors(d->simpleTransformation); 0134 } 0135 0136 void ColorDevice::scheduleUpdate() 0137 { 0138 d->updateTimer->start(); 0139 } 0140 0141 } // namespace KWin 0142 0143 #include "moc_colordevice.cpp"