diff --git a/common/control.cpp b/common/control.cpp index 236445b1cb8b01b9cd5ab89ac81ca642a0d1b87d..9a7ad018569dd0bd681ec813f738b9418536da49 100644 --- a/common/control.cpp +++ b/common/control.cpp @@ -29,6 +29,7 @@ #define vrrPolicyString QStringLiteral("vrrpolicy") #define rgbRangeString QStringLiteral("rgbrange") #define outputsString QStringLiteral("outputs") +#define bpcString QStringLiteral("bpc") // clang-format on QString Control::s_dirName = QStringLiteral("control/"); @@ -463,6 +464,16 @@ void ControlConfig::setRgbRange(const KScreen::OutputPtr &output, const KScreen: set(output, rgbRangeString, &ControlOutput::setRgbRange, value); } +uint32_t ControlConfig::getBpc(const KScreen::OutputPtr &output) const +{ + return get(output, bpcString, &ControlOutput::bpc, 8); +} + +void ControlConfig::setBpc(const KScreen::OutputPtr &output, uint32_t value) +{ + set(output, bpcString, &ControlOutput::setBpc, value); +} + QVariantList ControlConfig::getOutputs() const { return constInfo()[outputsString].toList(); @@ -612,3 +623,21 @@ void ControlOutput::setRgbRange(KScreen::Output::RgbRange value) } infoMap[rgbRangeString] = static_cast(value); } + +uint32_t ControlOutput::bpc() const +{ + const auto val = constInfo()[bpcString]; + if (val.canConvert()) { + return val.toUInt(); + } + return 8; +} + +void ControlOutput::setBpc(uint32_t bpc) +{ + auto &infoMap = info(); + if (infoMap.isEmpty()) { + infoMap = createOutputInfo(m_output->hashMd5(), m_output->name()); + } + infoMap[bpcString] = bpc; +} diff --git a/common/control.h b/common/control.h index 3b499d18eb535863c00b897d18f7529e450525a5..c4a5b4194296653b17bda95c85c461ada7b09753 100644 --- a/common/control.h +++ b/common/control.h @@ -87,6 +87,9 @@ public: KScreen::Output::RgbRange getRgbRange(const KScreen::OutputPtr &output) const; void setRgbRange(const KScreen::OutputPtr &output, const KScreen::Output::RgbRange value); + uint32_t getBpc(const KScreen::OutputPtr &output) const; + void setBpc(const KScreen::OutputPtr &output, uint32_t value); + QString dirPath() const override; QString filePath() const override; @@ -138,6 +141,9 @@ public: KScreen::Output::RgbRange rgbRange() const; void setRgbRange(KScreen::Output::RgbRange value); + uint32_t bpc() const; + void setBpc(uint32_t bpc); + QString dirPath() const override; QString filePath() const override; diff --git a/kcm/config_handler.cpp b/kcm/config_handler.cpp index d7e7c7c0c2702df8f348d3339b4d6176587b8b80..534c14122a684c9f403c3e34bc6aebde51381fa9 100644 --- a/kcm/config_handler.cpp +++ b/kcm/config_handler.cpp @@ -159,7 +159,8 @@ bool ConfigHandler::checkSaveandTestCommon(bool isSaveCheck) || autoRotateOnlyInTabletMode(output) != m_initialControl->getAutoRotateOnlyInTabletMode(output) || output->overscan() != config->overscan() || output->vrrPolicy() != config->vrrPolicy() - || output->rgbRange() != config->rgbRange()) { + || output->rgbRange() != config->rgbRange() + || output->bpc() != config->bpc()) { return true; } } @@ -357,6 +358,16 @@ void ConfigHandler::setRgbRange(const KScreen::OutputPtr &output, KScreen::Outpu m_control->setRgbRange(output, value); } +uint32_t ConfigHandler::bpc(const KScreen::OutputPtr &output) const +{ + return m_control->getBpc(output); +} + +void ConfigHandler::setBpc(const KScreen::OutputPtr &output, uint32_t value) +{ + m_control->setBpc(output, value); +} + void ConfigHandler::writeControl() { if (!m_control) { diff --git a/kcm/config_handler.h b/kcm/config_handler.h index a71200eb2dd59d850e03991fc164b26bfe084ff3..3a4040090b289270c86dcfe46c0cd13df16f22e6 100644 --- a/kcm/config_handler.h +++ b/kcm/config_handler.h @@ -68,6 +68,9 @@ public: KScreen::Output::RgbRange rgbRange(const KScreen::OutputPtr &output) const; void setRgbRange(const KScreen::OutputPtr &output, KScreen::Output::RgbRange value); + uint32_t bpc(const KScreen::OutputPtr &output) const; + void setBpc(const KScreen::OutputPtr &output, uint32_t value); + void writeControl(); void checkNeedsSave(); diff --git a/kcm/output_model.cpp b/kcm/output_model.cpp index a497c904d0d66a0e82e8ace5651141809eaf347a..ab60528c4ddfce392efdc9ebadb4fffb63e46432 100644 --- a/kcm/output_model.cpp +++ b/kcm/output_model.cpp @@ -84,6 +84,12 @@ QVariant OutputModel::data(const QModelIndex &index, int role) const return static_cast(output->vrrPolicy()); case RgbRangeRole: return static_cast(output->rgbRange()); + case MinBpcRole: + return output->minBpc(); + case MaxBpcRole: + return output->maxBpc(); + case BpcRole: + return output->bpc(); } return QVariant(); } @@ -212,6 +218,18 @@ bool OutputModel::setData(const QModelIndex &index, const QVariant &value, int r Q_EMIT dataChanged(index, index, {role}); return true; } + case BpcRole: + if (value.canConvert()) { + Output &output = m_outputs[index.row()]; + uint32_t bpc = value.toUInt(); + if (output.ptr->bpc() == bpc) { + return false; + } + output.ptr->setBpc(bpc); + m_config->setBpc(output.ptr, bpc); + Q_EMIT dataChanged(index, index, {role}); + return true; + } } return false; } @@ -240,6 +258,9 @@ QHash OutputModel::roleNames() const roles[OverscanRole] = "overscan"; roles[VrrPolicyRole] = "vrrPolicy"; roles[RgbRangeRole] = "rgbRange"; + roles[MinBpcRole] = "minBpc"; + roles[MaxBpcRole] = "maxBpc"; + roles[BpcRole] = "bpc"; return roles; } diff --git a/kcm/output_model.h b/kcm/output_model.h index 6c2b86f43ad82921afe6b67f531955840141281e..dbae921061de08f2406c2f361505681e1ffa908f 100644 --- a/kcm/output_model.h +++ b/kcm/output_model.h @@ -41,6 +41,9 @@ public: OverscanRole, VrrPolicyRole, RgbRangeRole, + MinBpcRole, + MaxBpcRole, + BpcRole }; explicit OutputModel(ConfigHandler *configHandler); diff --git a/kcm/package/contents/ui/OutputPanel.qml b/kcm/package/contents/ui/OutputPanel.qml index 810816fe9cd5c20fefd27bc4aae0d51d2c1607ae..6a8f78e478f9b566101c3cde7eb894194c9efd33 100644 --- a/kcm/package/contents/ui/OutputPanel.qml +++ b/kcm/package/contents/ui/OutputPanel.qml @@ -177,6 +177,23 @@ ColumnLayout { Component.onCompleted: currentIndex = indexOfValue(element.rgbRange); } + Controls.ComboBox { + Kirigami.FormData.label: i18n("Color bit depth:") + Layout.minimumWidth: Kirigami.Units.gridUnit * 11 + model: [ + { label: i18n("5"), value: 5 }, + { label: i18n("8"), value: 8 }, + { label: i18n("10"), value: 10 }, + { label: i18n("16"), value: 16 }, + ] + textRole: "label" + valueRole: "value" + visible: element.capabilities & KScreen.Output.Capability.Bpc + + onActivated: element.bpc = currentValue + Component.onCompleted: currentIndex = indexOfValue(element.bpc); + } + Controls.ComboBox { Kirigami.FormData.label: i18n("Replica of:") Layout.minimumWidth: Kirigami.Units.gridUnit * 11