backends/drm: disable software brightness if there was ever a hardware brightness device assigned

Software brightness is very useful when the backlight really can't be controlled by us, but if it's just temporarily
unavailable because of powerdevil not running, or DDC/CI having issues, then it's best if we don't darken the image
in software on top of the backlight level still being set by the display.
wilder/Plasma/6.3
Xaver Hugl 1 year ago
parent be0b1c2925
commit 4f18aae673
  1. 14
      src/backends/drm/drm_output.cpp
  2. 3
      src/core/brightnessdevice.cpp
  3. 5
      src/core/output.cpp
  4. 2
      src/core/output.h
  5. 1
      src/core/outputconfiguration.h
  6. 10
      src/outputconfigurationstore.cpp
  7. 1
      src/outputconfigurationstore.h
  8. 23
      src/workspace.cpp

@ -236,7 +236,7 @@ static const bool s_allowColorspaceNVidia = qEnvironmentVariableIntValue("KWIN_D
Output::Capabilities DrmOutput::computeCapabilities() const
{
Capabilities capabilities = Capability::Dpms | Capability::IccProfile | Capability::BrightnessControl;
Capabilities capabilities = Capability::Dpms | Capability::IccProfile;
if (m_connector->overscan.isValid() || m_connector->underscan.isValid()) {
capabilities |= Capability::Overscan;
}
@ -267,6 +267,9 @@ Output::Capabilities DrmOutput::computeCapabilities() const
// TODO only set this if an orientation sensor is available?
capabilities |= Capability::AutoRotation;
}
if (m_state.highDynamicRange || m_brightnessDevice || m_state.allowSdrSoftwareBrightness) {
capabilities |= Capability::BrightnessControl;
}
return capabilities;
}
@ -418,7 +421,8 @@ ColorDescription DrmOutput::createColorDescription(const std::shared_ptr<OutputC
// to work around that, (unless overridden by the user), assume the min. luminance of the transfer function instead
const double minBrightness = effectiveHdr ? props->minBrightnessOverride.value_or(m_state.minBrightnessOverride).value_or(TransferFunction::defaultMinLuminanceFor(TransferFunction::PerceptualQuantizer)) : transferFunction.minLuminance;
const double brightnessFactor = !m_brightnessDevice || effectiveHdr ? brightness : 1.0;
const bool allowSdrSoftwareBrightness = props->allowSdrSoftwareBrightness.value_or(m_state.allowSdrSoftwareBrightness);
const double brightnessFactor = (!m_brightnessDevice && allowSdrSoftwareBrightness) || effectiveHdr ? brightness : 1.0;
const double effectiveReferenceLuminance = 25 + (referenceLuminance - 25) * brightnessFactor;
return applyNightLight(ColorDescription(containerColorimetry, transferFunction, effectiveReferenceLuminance, minBrightness, maxAverageBrightness, maxPeakBrightness, masteringColorimetry, sdrColorimetry), m_channelFactors);
}
@ -456,8 +460,14 @@ void DrmOutput::applyQueuedChanges(const std::shared_ptr<OutputChangeSet> &props
next.brightnessSetting = props->brightness.value_or(m_state.brightnessSetting);
next.desiredModeSize = props->desiredModeSize.value_or(m_state.desiredModeSize);
next.desiredModeRefreshRate = props->desiredModeRefreshRate.value_or(m_state.desiredModeRefreshRate);
next.allowSdrSoftwareBrightness = props->allowSdrSoftwareBrightness.value_or(m_state.allowSdrSoftwareBrightness);
setState(next);
// allowSdrSoftwareBrightness might change our capabilities
Information newInfo = m_information;
newInfo.capabilities = computeCapabilities();
setInformation(newInfo);
if (!isEnabled() && m_pipeline->needsModeset()) {
m_gpu->maybeModeset(nullptr);
}

@ -18,9 +18,6 @@ BrightnessDevice::BrightnessDevice()
BrightnessDevice::~BrightnessDevice()
{
if (m_output) {
m_output->setBrightnessDevice(nullptr);
}
}
void BrightnessDevice::setOutput(Output *output)

@ -804,6 +804,11 @@ void Output::setBrightnessDevice(BrightnessDevice *device)
{
m_brightnessDevice = device;
}
bool Output::allowSdrSoftwareBrightness() const
{
return m_state.allowSdrSoftwareBrightness;
}
} // namespace KWin
#include "moc_output.cpp"

@ -371,6 +371,7 @@ public:
BrightnessDevice *brightnessDevice() const;
virtual void setBrightnessDevice(BrightnessDevice *device);
bool allowSdrSoftwareBrightness() const;
Q_SIGNALS:
/**
@ -491,6 +492,7 @@ protected:
double brightnessSetting = 1.0;
/// the actually applied brightness level
std::optional<double> currentBrightness;
bool allowSdrSoftwareBrightness = true;
};
void setInformation(const Information &information);

@ -46,6 +46,7 @@ public:
std::optional<double> sdrGamutWideness;
std::optional<Output::ColorProfileSource> colorProfileSource;
std::optional<double> brightness;
std::optional<bool> allowSdrSoftwareBrightness;
};
class KWIN_EXPORT OutputConfiguration

@ -234,6 +234,7 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
.minBrightnessOverride = changeSet->minBrightnessOverride.value_or(output->minBrightnessOverride()),
.sdrGamutWideness = changeSet->sdrGamutWideness.value_or(output->sdrGamutWideness()),
.brightness = changeSet->brightness.value_or(output->brightnessSetting()),
.allowSdrSoftwareBrightness = changeSet->allowSdrSoftwareBrightness.value_or(output->allowSdrSoftwareBrightness()),
};
*outputIt = SetupState{
.outputIndex = *outputIndex,
@ -276,6 +277,7 @@ void OutputConfigurationStore::storeConfig(const QList<Output *> &allOutputs, bo
.minBrightnessOverride = output->minBrightnessOverride(),
.sdrGamutWideness = output->sdrGamutWideness(),
.brightness = output->brightnessSetting(),
.allowSdrSoftwareBrightness = output->allowSdrSoftwareBrightness(),
};
*outputIt = SetupState{
.outputIndex = *outputIndex,
@ -331,6 +333,7 @@ std::pair<OutputConfiguration, QList<Output *>> OutputConfigurationStore::setupT
.sdrGamutWideness = state.sdrGamutWideness,
.colorProfileSource = state.colorProfileSource,
.brightness = state.brightness,
.allowSdrSoftwareBrightness = state.allowSdrSoftwareBrightness,
};
if (setupState.enabled) {
priorities.push_back(std::make_pair(output, setupState.priority));
@ -455,6 +458,7 @@ std::pair<OutputConfiguration, QList<Output *>> OutputConfigurationStore::genera
.autoRotationPolicy = existingData.autoRotation.value_or(Output::AutoRotationPolicy::InTabletMode),
.colorProfileSource = existingData.colorProfileSource.value_or(Output::ColorProfileSource::sRGB),
.brightness = existingData.brightness.value_or(1.0),
.allowSdrSoftwareBrightness = existingData.allowSdrSoftwareBrightness.value_or(output->brightnessDevice() == nullptr),
};
if (enable) {
const auto modeSize = changeset->transform->map(mode->size());
@ -765,6 +769,9 @@ void OutputConfigurationStore::load()
if (const auto it = data.find("brightness"); it != data.end() && it->isDouble()) {
state.brightness = std::clamp(it->toDouble(), 0.0, 1.0);
}
if (const auto it = data.find("allowSdrSoftwareBrightness"); it != data.end() && it->isBool()) {
state.allowSdrSoftwareBrightness = it->toBool();
}
outputDatas.push_back(state);
}
@ -997,6 +1004,9 @@ void OutputConfigurationStore::save()
if (output.brightness) {
o["brightness"] = *output.brightness;
}
if (output.allowSdrSoftwareBrightness) {
o["allowSdrSoftwareBrightness"] = *output.allowSdrSoftwareBrightness;
}
outputsData.append(o);
}
outputs["data"] = outputsData;

@ -83,6 +83,7 @@ private:
std::optional<double> minBrightnessOverride;
std::optional<double> sdrGamutWideness;
std::optional<double> brightness;
std::optional<bool> allowSdrSoftwareBrightness;
};
struct SetupState
{

@ -260,7 +260,7 @@ void Workspace::init()
m_placementTracker->init(getPlacementTrackerHash());
if (waylandServer()) {
connect(waylandServer()->externalBrightness(), &ExternalBrightnessV1::devicesChanged, this, &Workspace::assignBrightnessDevices);
connect(waylandServer()->externalBrightness(), &ExternalBrightnessV1::devicesChanged, this, &Workspace::updateOutputConfiguration);
}
}
@ -538,11 +538,19 @@ void Workspace::updateOutputConfiguration()
setOutputOrder(newOrder);
};
const auto opt = m_outputConfigStore->queryConfig(outputs, m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(), kwinApp()->tabletModeManager()->effectiveTabletMode());
auto opt = m_outputConfigStore->queryConfig(outputs, m_lidSwitchTracker->isLidClosed(), m_orientationSensor->reading(), kwinApp()->tabletModeManager()->effectiveTabletMode());
if (!opt) {
return;
}
const auto &[cfg, order, type] = *opt;
auto &[cfg, order, type] = *opt;
assignBrightnessDevices();
for (Output *output : outputs) {
if (output->brightnessDevice()) {
cfg.changeSet(output)->allowSdrSoftwareBrightness = false;
}
}
if (!applyOutputConfiguration(cfg, order)) {
qCWarning(KWIN_CORE) << "Applying output config failed!";
setFallbackOutputOrder();
@ -1324,10 +1332,6 @@ void Workspace::updateOutputs(const std::optional<QList<Output *>> &outputOrder)
m_placementTracker->uninhibit();
m_placementTracker->restore(getPlacementTrackerHash());
if (!added.isEmpty() || !removed.isEmpty()) {
assignBrightnessDevices();
}
for (Output *output : removed) {
output->unref();
}
@ -1358,7 +1362,7 @@ void Workspace::assignBrightnessDevices()
if (!waylandServer()) {
return;
}
QList<Output *> candidates = m_outputs;
QList<Output *> candidates = kwinApp()->outputBackend()->outputs();
const auto devices = waylandServer()->externalBrightness()->devices();
for (BrightnessDevice *device : devices) {
// assign the device to the most fitting output
@ -1388,6 +1392,9 @@ void Workspace::assignBrightnessDevices()
}
}
}
for (Output *output : candidates) {
output->setBrightnessDevice(nullptr);
}
}
void Workspace::slotDesktopAdded(VirtualDesktop *desktop)

Loading…
Cancel
Save