diff --git a/autotests/client/test_wayland_outputdevice.cpp b/autotests/client/test_wayland_outputdevice.cpp --- a/autotests/client/test_wayland_outputdevice.cpp +++ b/autotests/client/test_wayland_outputdevice.cpp @@ -46,6 +46,7 @@ void testModeChanges(); void testScaleChange_legacy(); void testScaleChange(); + void testColorCurvesChange(); void testSubPixel_data(); void testSubPixel(); @@ -62,6 +63,7 @@ KWayland::Server::Display *m_display; KWayland::Server::OutputDeviceInterface *m_serverOutputDevice; QByteArray m_edid; + KWayland::Server::OutputDeviceInterface::ColorCurves m_initColorCurves; KWayland::Client::ConnectionThread *m_connection; KWayland::Client::EventQueue *m_queue; QThread *m_thread; @@ -115,6 +117,21 @@ m_edid = QByteArray::fromBase64("AP///////wAQrBbwTExLQQ4WAQOANCB46h7Frk80sSYOUFSlSwCBgKlA0QBxTwEBAQEBAQEBKDyAoHCwI0AwIDYABkQhAAAaAAAA/wBGNTI1TTI0NUFLTEwKAAAA/ABERUxMIFUyNDEwCiAgAAAA/QA4TB5REQAKICAgICAgAToCAynxUJAFBAMCBxYBHxITFCAVEQYjCQcHZwMMABAAOC2DAQAA4wUDAQI6gBhxOC1AWCxFAAZEIQAAHgEdgBhxHBYgWCwlAAZEIQAAngEdAHJR0B4gbihVAAZEIQAAHowK0Iog4C0QED6WAAZEIQAAGAAAAAAAAAAAAAAAAAAAPg=="); m_serverOutputDevice->setEdid(m_edid); + m_initColorCurves.red.clear(); + m_initColorCurves.green.clear(); + m_initColorCurves.blue.clear(); + // 8 bit color ramps + for (int i = 0; i < 256; i++) { + quint16 val = (double)i / 255 * UINT16_MAX; + m_initColorCurves.red << val ; + m_initColorCurves.green << val ; + } + // 10 bit color ramp + for (int i = 0; i < 320; i++) { + m_initColorCurves.blue << (double)i / 319 * UINT16_MAX; + } + m_serverOutputDevice->setColorCurves(m_initColorCurves); + m_serverOutputDevice->create(); // setup connection @@ -183,6 +200,9 @@ QCOMPARE(output.pixelSize(), QSize()); QCOMPARE(output.refreshRate(), 0); QCOMPARE(output.scale(), 1); + QCOMPARE(output.colorCurves().red, QVector()); + QCOMPARE(output.colorCurves().green, QVector()); + QCOMPARE(output.colorCurves().blue, QVector()); QCOMPARE(output.subPixel(), KWayland::Client::OutputDevice::SubPixel::Unknown); QCOMPARE(output.transform(), KWayland::Client::OutputDevice::Transform::Normal); QCOMPARE(output.enabled(), OutputDevice::Enablement::Enabled); @@ -203,6 +223,9 @@ QCOMPARE(output.pixelSize(), QSize(1024, 768)); QCOMPARE(output.refreshRate(), 60000); QCOMPARE(output.scale(), 1); + QCOMPARE(output.colorCurves().red, m_initColorCurves.red); + QCOMPARE(output.colorCurves().green, m_initColorCurves.green); + QCOMPARE(output.colorCurves().blue, m_initColorCurves.blue); // for xwayland output it's unknown QCOMPARE(output.subPixel(), KWayland::Client::OutputDevice::SubPixel::Unknown); // for xwayland transform is normal @@ -384,6 +407,53 @@ QCOMPARE(wl_fixed_from_double(output.scaleF()), wl_fixed_from_double(4.9)); } +void TestWaylandOutputDevice::testColorCurvesChange() +{ + KWayland::Client::Registry registry; + QSignalSpy interfacesAnnouncedSpy(®istry, &KWayland::Client::Registry::interfacesAnnounced); + QVERIFY(interfacesAnnouncedSpy.isValid()); + QSignalSpy announced(®istry, &KWayland::Client::Registry::outputDeviceAnnounced); + registry.setEventQueue(m_queue); + registry.create(m_connection->display()); + QVERIFY(registry.isValid()); + registry.setup(); + wl_display_flush(m_connection->display()); + QVERIFY(interfacesAnnouncedSpy.wait()); + + KWayland::Client::OutputDevice output; + QSignalSpy outputChanged(&output, &KWayland::Client::OutputDevice::done); + QVERIFY(outputChanged.isValid()); + output.setup(registry.bindOutputDevice(announced.first().first().value(), announced.first().last().value())); + wl_display_flush(m_connection->display()); + QVERIFY(outputChanged.wait()); + QCOMPARE(output.colorCurves().red, m_initColorCurves.red); + QCOMPARE(output.colorCurves().green, m_initColorCurves.green); + QCOMPARE(output.colorCurves().blue, m_initColorCurves.blue); + + // change the color curves + outputChanged.clear(); + KWayland::Server::OutputDeviceInterface::ColorCurves cc; + cc.red = QVector(256, 0); + cc.green = QVector(256, UINT16_MAX); + cc.blue = QVector(320, 1); + m_serverOutputDevice->setColorCurves(cc); + QVERIFY(outputChanged.wait()); + QCOMPARE(output.colorCurves().red, cc.red); + QCOMPARE(output.colorCurves().green, cc.green); + QCOMPARE(output.colorCurves().blue, cc.blue); + + // change once more + outputChanged.clear(); + cc.red = QVector(256, 0); + cc.green = QVector(256, UINT16_MAX); + cc.blue = QVector(320, UINT16_MAX); + m_serverOutputDevice->setColorCurves(cc); + QVERIFY(outputChanged.wait()); + QCOMPARE(output.colorCurves().red, cc.red); + QCOMPARE(output.colorCurves().green, cc.green); + QCOMPARE(output.colorCurves().blue, cc.blue); +} + void TestWaylandOutputDevice::testSubPixel_data() { using namespace KWayland::Client; diff --git a/autotests/client/test_wayland_outputmanagement.cpp b/autotests/client/test_wayland_outputmanagement.cpp --- a/autotests/client/test_wayland_outputmanagement.cpp +++ b/autotests/client/test_wayland_outputmanagement.cpp @@ -250,6 +250,9 @@ if (c->scaleChanged()) { outputdevice->setScaleF(c->scaleF()); } + if (c->colorCurvesChanged()) { + outputdevice->setColorCurves(c->colorCurves()); + } } } @@ -268,6 +271,9 @@ QCOMPARE(output->pixelSize(), QSize()); QCOMPARE(output->refreshRate(), 0); QCOMPARE(output->scale(), 1); + QCOMPARE(output->colorCurves().red, QVector()); + QCOMPARE(output->colorCurves().green, QVector()); + QCOMPARE(output->colorCurves().blue, QVector()); QCOMPARE(output->subPixel(), KWayland::Client::OutputDevice::SubPixel::Unknown); QCOMPARE(output->transform(), KWayland::Client::OutputDevice::Transform::Normal); QCOMPARE(output->enabled(), OutputDevice::Enablement::Enabled); @@ -405,6 +411,8 @@ config->setTransform(output, OutputDevice::Transform::Rotated90); config->setPosition(output, QPoint(13, 37)); config->setScale(output, 2); + const auto zeroVector = QVector(256, 0); + config->setColorCurves(output, zeroVector, zeroVector, zeroVector); config->setEnabled(output, OutputDevice::Enablement::Disabled); config->apply(); @@ -423,6 +431,8 @@ config->setTransform(output, OutputDevice::Transform::Normal); config->setPosition(output, QPoint(0, 1920)); config->setScale(output, 1); + const auto oneVector = QVector(256, 1); + config->setColorCurves(output, oneVector, oneVector, oneVector); config->setEnabled(output, OutputDevice::Enablement::Enabled); config->apply(); diff --git a/src/client/outputconfiguration.h b/src/client/outputconfiguration.h --- a/src/client/outputconfiguration.h +++ b/src/client/outputconfiguration.h @@ -22,6 +22,7 @@ #include #include +#include #include "outputdevice.h" #include @@ -209,6 +210,21 @@ */ void setScaleF(OutputDevice *outputdevice, qreal scale); + /* Set color curves for this output. The respective color curve vector + * lengths must equal the current ones in the OutputDevice. The codomain + * of the curves is always the full uint16 value range, such that any vector + * is accepted as long as it has the right size. + * The changes done in this call will be recorded in the + * OutputDevice and only applied after apply() has been called. + * + * @param red color curve of red channel. + * @param green color curve of green channel. + * @param blue color curve of blue channel. + * @param outputdevice the OutputDevice this change applies to. + * @since 5.50 + */ + void setColorCurves(OutputDevice *outputdevice, QVector red, QVector green, QVector blue); + /** * Ask the compositor to apply the changes. * This results in the compositor looking at all outputdevices and if they have diff --git a/src/client/outputconfiguration.cpp b/src/client/outputconfiguration.cpp --- a/src/client/outputconfiguration.cpp +++ b/src/client/outputconfiguration.cpp @@ -177,6 +177,30 @@ } } +void OutputConfiguration::setColorCurves(OutputDevice *outputdevice, + QVector red, QVector green, QVector blue) +{ + org_kde_kwin_outputdevice *od = outputdevice->output(); + + wl_array wlRed, wlGreen, wlBlue; + + auto fillArray = [](QVector &origin, wl_array *dest) { + wl_array_init(dest); + const size_t memLength = sizeof(uint16_t) * origin.size(); + void *s = wl_array_add(dest, memLength); + memcpy(s, origin.data(), memLength); + }; + fillArray(red, &wlRed); + fillArray(green, &wlGreen); + fillArray(blue, &wlBlue); + + org_kde_kwin_outputconfiguration_colorcurves(d->outputconfiguration, od, &wlRed, &wlGreen, &wlBlue); + + wl_array_release(&wlRed); + wl_array_release(&wlGreen); + wl_array_release(&wlBlue); +} + void OutputConfiguration::apply() { org_kde_kwin_outputconfiguration_apply(d->outputconfiguration); diff --git a/src/client/outputdevice.h b/src/client/outputdevice.h --- a/src/client/outputdevice.h +++ b/src/client/outputdevice.h @@ -1,5 +1,6 @@ /******************************************************************** Copyright 2013 Martin Gräßlin +Copyright 2018 Roman Gilg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -23,6 +24,7 @@ #include #include #include +#include #include @@ -126,6 +128,12 @@ bool operator==(const Mode &m) const; }; + struct ColorCurves { + QVector red, green, blue; + + bool operator==(const ColorCurves &cc) const; + bool operator!=(const ColorCurves &cc) const; + }; explicit OutputDevice(QObject *parent = nullptr); virtual ~OutputDevice(); @@ -205,6 +213,11 @@ * directly from client surfaces. **/ Transform transform() const; + /** + * Color curves. + * @since 5.50 + **/ + ColorCurves colorCurves() const; /** * @returns The Modes of this OutputDevice. @@ -281,6 +294,12 @@ * @param mode The changed Mode **/ void modeChanged(const KWayland::Client::OutputDevice::Mode &mode); + /** + * Emitted whenever the color curves changed. + * + * @since 5.TODO + **/ + void colorCurvesChanged(); /** * The corresponding global for this interface on the Registry got removed. * @@ -303,6 +322,7 @@ Q_DECLARE_METATYPE(KWayland::Client::OutputDevice::Transform) Q_DECLARE_METATYPE(KWayland::Client::OutputDevice::Enablement) Q_DECLARE_METATYPE(KWayland::Client::OutputDevice::Mode) +Q_DECLARE_METATYPE(KWayland::Client::OutputDevice::ColorCurves) Q_DECLARE_OPERATORS_FOR_FLAGS(KWayland::Client::OutputDevice::Mode::Flags) #endif diff --git a/src/client/outputdevice.cpp b/src/client/outputdevice.cpp --- a/src/client/outputdevice.cpp +++ b/src/client/outputdevice.cpp @@ -1,5 +1,6 @@ /******************************************************************** Copyright 2013 Martin Gräßlin +Copyright 2018 Roman Gilg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -58,6 +59,9 @@ QByteArray edid; OutputDevice::Enablement enabled = OutputDevice::Enablement::Enabled; QByteArray uuid; + + ColorCurves colorCurves; + bool done = false; private: @@ -73,6 +77,9 @@ static void enabledCallback(void *data, org_kde_kwin_outputdevice *output, int32_t enabled); static void uuidCallback(void *data, org_kde_kwin_outputdevice *output, const char *uuid); + static void colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output, + wl_array *red, wl_array *green, wl_array *blue); + void setPhysicalSize(const QSize &size); void setGlobalPosition(const QPoint &pos); void setManufacturer(const QString &manufacturer); @@ -107,6 +114,14 @@ && output == m.output; } +bool OutputDevice::ColorCurves::operator==(const OutputDevice::ColorCurves &cc) const +{ + return red == cc.red && green == cc.green && blue == cc.blue; +} +bool OutputDevice::ColorCurves::operator!=(const ColorCurves &cc) const { + return !operator==(cc); +} + OutputDevice::OutputDevice(QObject *parent) : QObject(parent) , d(new Private(this)) @@ -126,7 +141,8 @@ edidCallback, enabledCallback, uuidCallback, - scaleFCallback + scaleFCallback, + colorcurvesCallback }; void OutputDevice::Private::geometryCallback(void *data, org_kde_kwin_outputdevice *output, @@ -301,6 +317,33 @@ } } +void OutputDevice::Private::colorcurvesCallback(void *data, org_kde_kwin_outputdevice *output, + wl_array *red, + wl_array *green, + wl_array *blue) +{ + Q_UNUSED(output); + auto o = reinterpret_cast(data); + + auto cc = ColorCurves(); + + auto setCurve = [](const wl_array *curve, QVector *destination) { + destination->resize(curve->size / sizeof(uint16_t)); + memcpy(destination->data(), curve->data, curve->size); + }; + setCurve(red, &cc.red); + setCurve(green, &cc.green); + setCurve(blue, &cc.blue); + + if (o->colorCurves != cc) { + o->colorCurves = cc; + emit o->q->colorCurvesChanged(); + if (o->done) { + emit o->q->changed(); + } + } +} + void OutputDevice::setup(org_kde_kwin_outputdevice *output) { d->setup(output); @@ -454,6 +497,11 @@ return d->uuid; } +OutputDevice::ColorCurves OutputDevice::colorCurves() const +{ + return d->colorCurves; +} + void OutputDevice::destroy() { d->output.destroy(); diff --git a/src/client/protocols/output-management.xml b/src/client/protocols/output-management.xml --- a/src/client/protocols/output-management.xml +++ b/src/client/protocols/output-management.xml @@ -172,6 +172,20 @@ + + + Set color curves of output devices through RGB color ramps. Allows color + correction of output device from user space. + + These are the raw values. A compositor might opt to adjust these values + internally, for example to shift color temperature at night. + + + + + + + diff --git a/src/client/protocols/outputdevice.xml b/src/client/protocols/outputdevice.xml --- a/src/client/protocols/outputdevice.xml +++ b/src/client/protocols/outputdevice.xml @@ -255,7 +255,23 @@ + + + Decribes the color intensity profile of the output. + Commonly used for gamma/color correction. + The array contains all color ramp values of the output. + For example on 8bit screens there are 256 of them. + + The array elements are unsigned 16bit integers. + + + + + diff --git a/src/server/outputchangeset.h b/src/server/outputchangeset.h --- a/src/server/outputchangeset.h +++ b/src/server/outputchangeset.h @@ -69,6 +69,10 @@ * @returns @c true if the scale() property of the outputdevice has changed. */ bool scaleChanged() const; + /** Whether the colorCurves() property of the outputdevice changed. + * @returns @c true if the colorCurves() property of the outputdevice has changed. + */ + bool colorCurvesChanged() const; /** The new value for enabled. */ OutputDeviceInterface::Enablement enabled() const; @@ -86,6 +90,10 @@ * @since 5.XX */ qreal scaleF() const; + /** The new value for colorCurves. + * @since 5.XX + */ + OutputDeviceInterface::ColorCurves colorCurves() const; private: friend class OutputConfigurationInterface; diff --git a/src/server/outputchangeset.cpp b/src/server/outputchangeset.cpp --- a/src/server/outputchangeset.cpp +++ b/src/server/outputchangeset.cpp @@ -34,6 +34,7 @@ , transform(o->transform()) , position(o->globalPosition()) , scale(o->scale()) + , colorCurves(o->colorCurves()) { } @@ -117,5 +118,17 @@ return d->scale; } +bool OutputChangeSet::colorCurvesChanged() const +{ + Q_D(); + return d->colorCurves != d->o->colorCurves(); +} + +OutputDeviceInterface::ColorCurves OutputChangeSet::colorCurves() const +{ + Q_D(); + return d->colorCurves; +} + } } diff --git a/src/server/outputchangeset_p.h b/src/server/outputchangeset_p.h --- a/src/server/outputchangeset_p.h +++ b/src/server/outputchangeset_p.h @@ -41,6 +41,7 @@ OutputDeviceInterface::Transform transform; QPoint position; qreal scale; + OutputDeviceInterface::ColorCurves colorCurves; }; } } diff --git a/src/server/outputconfiguration_interface.cpp b/src/server/outputconfiguration_interface.cpp --- a/src/server/outputconfiguration_interface.cpp +++ b/src/server/outputconfiguration_interface.cpp @@ -71,6 +71,9 @@ static void applyCallback(wl_client *client, wl_resource *resource); static void scaleFCallback(wl_client *client, wl_resource *resource, wl_resource * outputdevice, wl_fixed_t scale); + static void colorcurvesCallback(wl_client *client, wl_resource *resource, + wl_resource * outputdevice, + wl_array *red, wl_array *green, wl_array *blue); OutputConfigurationInterface *q_func() { return reinterpret_cast(q); @@ -87,6 +90,7 @@ scaleCallback, applyCallback, scaleFCallback, + colorcurvesCallback, resourceDestroyedCallback }; @@ -213,6 +217,42 @@ s->emitConfigurationChangeRequested(); } +void OutputConfigurationInterface::Private::colorcurvesCallback(wl_client *client, wl_resource *resource, + wl_resource * outputdevice, + wl_array *red, wl_array *green, wl_array *blue) +{ + Q_UNUSED(client); + OutputDeviceInterface *o = OutputDeviceInterface::get(outputdevice); + OutputDeviceInterface::ColorCurves oldCc = o->colorCurves(); + + auto checkArg = [](const wl_array *newColor, const QVector &oldColor) { + return (newColor->size % sizeof(uint16_t) == 0) && + (newColor->size / sizeof(uint16_t) == static_cast(oldColor.size())); + }; + if (!checkArg(red, oldCc.red) || !checkArg(green, oldCc.green) || !checkArg(blue, oldCc.blue)) { + qCWarning(KWAYLAND_SERVER) << "Requested to change color curves, but have wrong size."; + return; + } + + auto s = cast(resource); + Q_ASSERT(s); + OutputDeviceInterface::ColorCurves cc; + + auto fillVector = [](const wl_array *array, QVector *v) { + const uint16_t *pos = (uint16_t*)array->data; + + while((char*)pos < (char*)array->data + array->size) { + v->append(*pos); + pos++; + } + }; + fillVector(red, &cc.red); + fillVector(green, &cc.green); + fillVector(blue, &cc.blue); + + s->pendingChanges(o)->d_func()->colorCurves = cc; +} + void OutputConfigurationInterface::Private::emitConfigurationChangeRequested() const { auto configinterface = reinterpret_cast(q); diff --git a/src/server/outputdevice_interface.h b/src/server/outputdevice_interface.h --- a/src/server/outputdevice_interface.h +++ b/src/server/outputdevice_interface.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "global.h" @@ -91,6 +92,11 @@ ModeFlags flags; int id = -1; }; + struct ColorCurves { + QVector red, green, blue; + bool operator==(const ColorCurves &cc) const; + bool operator!=(const ColorCurves &cc) const; + }; virtual ~OutputDeviceInterface(); QSize physicalSize() const; @@ -103,6 +109,7 @@ qreal scaleF() const; SubPixel subPixel() const; Transform transform() const; + ColorCurves colorCurves() const; QList modes() const; int currentModeId() const; @@ -118,6 +125,7 @@ void setScaleF(qreal scale); void setSubPixel(SubPixel subPixel); void setTransform(Transform transform); + void setColorCurves(const ColorCurves &colorCurves); void addMode(Mode &mode); void setCurrentMode(const int modeId); @@ -140,6 +148,7 @@ void scaleFChanged(qreal); void subPixelChanged(SubPixel); void transformChanged(Transform); + void colorCurvesChanged(ColorCurves); void modesChanged(); void currentModeChanged(); @@ -161,5 +170,6 @@ Q_DECLARE_METATYPE(KWayland::Server::OutputDeviceInterface::Enablement) Q_DECLARE_METATYPE(KWayland::Server::OutputDeviceInterface::SubPixel) Q_DECLARE_METATYPE(KWayland::Server::OutputDeviceInterface::Transform) +Q_DECLARE_METATYPE(KWayland::Server::OutputDeviceInterface::ColorCurves) #endif diff --git a/src/server/outputdevice_interface.cpp b/src/server/outputdevice_interface.cpp --- a/src/server/outputdevice_interface.cpp +++ b/src/server/outputdevice_interface.cpp @@ -45,6 +45,7 @@ void sendDone(const ResourceData &data); void updateGeometry(); void updateScale(); + void updateColorCurves(); void sendUuid(); void sendEdid(); @@ -57,6 +58,7 @@ qreal scale = 1.0; SubPixel subPixel = SubPixel::Unknown; Transform transform = Transform::Normal; + ColorCurves colorCurves; QList modes; QList resources; @@ -74,6 +76,7 @@ int32_t toSubPixel() const; void sendGeometry(wl_resource *resource); void sendScale(const ResourceData &data); + void sendColorCurves(const ResourceData &data); static const quint32 s_version; OutputDeviceInterface *q; @@ -139,6 +142,8 @@ connect(this, &OutputDeviceInterface::modelChanged, this, [this, d] { d->updateGeometry(); }); connect(this, &OutputDeviceInterface::manufacturerChanged, this, [this, d] { d->updateGeometry(); }); connect(this, &OutputDeviceInterface::scaleFChanged, this, [this, d] { d->updateScale(); }); + connect(this, &OutputDeviceInterface::scaleChanged, this, [this, d] { d->updateScale(); }); + connect(this, &OutputDeviceInterface::colorCurvesChanged, this, [this, d] { d->updateColorCurves(); }); } OutputDeviceInterface::~OutputDeviceInterface() = default; @@ -333,6 +338,7 @@ sendGeometry(resource); sendScale(r); + sendColorCurves(r); auto currentModeIt = modes.constEnd(); for (auto it = modes.constBegin(); it != modes.constEnd(); ++it) { @@ -409,6 +415,31 @@ } } +void OutputDeviceInterface::Private::sendColorCurves(const ResourceData &data) +{ + if (data.version < ORG_KDE_KWIN_OUTPUTDEVICE_COLORCURVES_SINCE_VERSION) { + return; + } + + wl_array wlRed, wlGreen, wlBlue; + + auto fillArray = [](const QVector &origin, wl_array *dest) { + wl_array_init(dest); + const size_t memLength = sizeof(uint16_t) * origin.size(); + void *s = wl_array_add(dest, memLength); + memcpy(s, origin.data(), memLength); + }; + fillArray(colorCurves.red, &wlRed); + fillArray(colorCurves.green, &wlGreen); + fillArray(colorCurves.blue, &wlBlue); + + org_kde_kwin_outputdevice_send_colorcurves(data.resource, &wlRed, &wlGreen, &wlBlue); + + wl_array_release(&wlRed); + wl_array_release(&wlGreen); + wl_array_release(&wlBlue); +} + void OutputDeviceInterface::Private::sendDone(const ResourceData &data) { org_kde_kwin_outputdevice_send_done(data.resource); @@ -430,6 +461,22 @@ } } +void OutputDeviceInterface::Private::updateColorCurves() +{ + for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) { + sendColorCurves(*it); + sendDone(*it); + } +} + +bool OutputDeviceInterface::ColorCurves::operator==(const ColorCurves &cc) const +{ + return red == cc.red && green == cc.green && blue == cc.blue; +} +bool OutputDeviceInterface::ColorCurves::operator!=(const ColorCurves &cc) const { + return !operator==(cc); +} + #define SETTER(setterName, type, argumentName) \ void OutputDeviceInterface::setterName(type arg) \ { \ @@ -521,6 +568,12 @@ return d->transform; } +OutputDeviceInterface::ColorCurves OutputDeviceInterface::colorCurves() const +{ + Q_D(); + return d->colorCurves; +} + QList< OutputDeviceInterface::Mode > OutputDeviceInterface::modes() const { Q_D(); @@ -543,6 +596,17 @@ return reinterpret_cast(d.data()); } +void OutputDeviceInterface::setColorCurves(const ColorCurves &colorCurves) +{ + Q_D(); + + if (d->colorCurves == colorCurves) { + return; + } + d->colorCurves = colorCurves; + emit colorCurvesChanged(d->colorCurves); +} + void OutputDeviceInterface::setEdid(const QByteArray &edid) { Q_D();