From 9d4fe3adf15dfd8a3147743058ba7a5a94fcdc6d Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Wed, 25 Oct 2023 18:36:33 +0200 Subject: [PATCH] implement the frog color management protocol --- src/backends/drm/drm_output.cpp | 1 + src/core/output.cpp | 5 + src/core/output.h | 3 + src/scene/dndiconitem.cpp | 1 + src/wayland/CMakeLists.txt | 8 +- src/wayland/frog_colormanagement_v1.cpp | 158 ++++++++ src/wayland/frog_colormanagement_v1.h | 62 +++ .../protocols/frog-color-management-v1.xml | 356 ++++++++++++++++++ src/wayland/surface.cpp | 18 + src/wayland/surface.h | 2 + src/wayland/surface_p.h | 3 + src/wayland_server.cpp | 2 + src/waylandwindow.cpp | 1 + 13 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 src/wayland/frog_colormanagement_v1.cpp create mode 100644 src/wayland/frog_colormanagement_v1.h create mode 100644 src/wayland/protocols/frog-color-management-v1.xml diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 55475d41f5..b1ff8e97ea 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -354,6 +354,7 @@ void DrmOutput::applyQueuedChanges(const std::shared_ptr &props if (m_state.highDynamicRange != next.highDynamicRange || m_state.sdrBrightness != next.sdrBrightness || m_state.wideColorGamut != next.wideColorGamut || m_state.iccProfile != next.iccProfile) { m_renderLoop->scheduleRepaint(); } + next.colorDescription = m_pipeline->colorDescription(); setState(next); setVrrPolicy(props->vrrPolicy.value_or(vrrPolicy())); diff --git a/src/core/output.cpp b/src/core/output.cpp index fd354f76cd..2877fbc82f 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -599,6 +599,11 @@ bool Output::updateCursorLayer() return false; } +const ColorDescription &Output::colorDescription() const +{ + return m_state.colorDescription; +} + } // namespace KWin #include "moc_output.cpp" diff --git a/src/core/output.h b/src/core/output.h index 277b9a325d..8e94196cf8 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -335,6 +335,8 @@ public: virtual bool updateCursorLayer(); + const ColorDescription &colorDescription() const; + Q_SIGNALS: /** * This signal is emitted when the geometry of this output has changed. @@ -433,6 +435,7 @@ protected: AutoRotationPolicy autoRotatePolicy = AutoRotationPolicy::InTabletMode; QString iccProfilePath; std::shared_ptr iccProfile; + ColorDescription colorDescription = ColorDescription::sRGB; }; void setInformation(const Information &information); diff --git a/src/scene/dndiconitem.cpp b/src/scene/dndiconitem.cpp index 84acde3bb5..2be8c0900f 100644 --- a/src/scene/dndiconitem.cpp +++ b/src/scene/dndiconitem.cpp @@ -41,6 +41,7 @@ void DragAndDropIconItem::setOutput(Output *output) { if (m_surfaceItem && output) { m_surfaceItem->surface()->setPreferredBufferScale(output->scale()); + m_surfaceItem->surface()->setPreferredColorDescription(output->colorDescription()); } } diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index bfec8f9c91..8a2bf9fd4f 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -216,6 +216,10 @@ ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml PROTOCOL protocols/qt-toplevel-drag-v1.xml BASENAME qt-toplevel-drag-v1 ) +ecm_add_qtwayland_server_protocol_kde(WaylandProtocols_xml + PROTOCOL ${PROJECT_SOURCE_DIR}/src/wayland/protocols/frog-color-management-v1.xml + BASENAME frog-color-management-v1 +) target_sources(kwin PRIVATE abstract_data_source.cpp @@ -239,8 +243,9 @@ target_sources(kwin PRIVATE dpms.cpp drmclientbuffer.cpp drmlease_v1.cpp - fractionalscale_v1.cpp filtered_display.cpp + fractionalscale_v1.cpp + frog_colormanagement_v1.cpp idle.cpp idleinhibit_v1.cpp idlenotify_v1.cpp @@ -314,6 +319,7 @@ install(FILES dpms.h drmlease_v1.h fractionalscale_v1.h + frog_colormanagement_v1.h idle.h idleinhibit_v1.h idlenotify_v1.h diff --git a/src/wayland/frog_colormanagement_v1.cpp b/src/wayland/frog_colormanagement_v1.cpp new file mode 100644 index 0000000000..c0187b1b26 --- /dev/null +++ b/src/wayland/frog_colormanagement_v1.cpp @@ -0,0 +1,158 @@ +/* + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ +#include "frog_colormanagement_v1.h" +#include "display.h" +#include "surface.h" +#include "surface_p.h" + +namespace KWin +{ + +static constexpr uint32_t s_version = 1; + +FrogColorManagementV1::FrogColorManagementV1(Display *display, QObject *parent) + : QObject(parent) + , QtWaylandServer::frog_color_management_factory_v1(*display, s_version) +{ +} + +FrogColorManagementV1::~FrogColorManagementV1() +{ +} + +void FrogColorManagementV1::frog_color_management_factory_v1_get_color_managed_surface(Resource *resource, wl_resource *surface, uint32_t callback) +{ + SurfaceInterface *surf = SurfaceInterface::get(surface); + SurfaceInterfacePrivate::get(surf)->frogColorManagement = new FrogColorManagementSurfaceV1(surf, resource->client(), callback); +} + +void FrogColorManagementV1::frog_color_management_factory_v1_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +FrogColorManagementSurfaceV1::FrogColorManagementSurfaceV1(SurfaceInterface *surface, wl_client *client, uint32_t id) + : QtWaylandServer::frog_color_managed_surface(client, id, s_version) + , m_surface(surface) +{ +} + +FrogColorManagementSurfaceV1::~FrogColorManagementSurfaceV1() +{ + if (m_surface) { + const auto priv = SurfaceInterfacePrivate::get(m_surface); + priv->pending->colorDescription = ColorDescription::sRGB; + priv->pending->colorDescriptionIsSet = true; + priv->frogColorManagement = nullptr; + } +} + +static QtWaylandServer::frog_color_managed_surface::transfer_function kwinToFrogTransferFunction(NamedTransferFunction tf) +{ + switch (tf) { + case NamedTransferFunction::sRGB: + return QtWaylandServer::frog_color_managed_surface::transfer_function_srgb; + case NamedTransferFunction::PerceptualQuantizer: + return QtWaylandServer::frog_color_managed_surface::transfer_function_st2084_pq; + case NamedTransferFunction::scRGB: + return QtWaylandServer::frog_color_managed_surface::transfer_function_scrgb_linear; + case NamedTransferFunction::linear: + return QtWaylandServer::frog_color_managed_surface::transfer_function_scrgb_linear; + } + return QtWaylandServer::frog_color_managed_surface::transfer_function_undefined; +} + +uint16_t encodePrimary(float primary) +{ + return uint16_t(std::clamp(std::round(primary / 0.00002), 0, 0xC350)); +} + +void FrogColorManagementSurfaceV1::setPreferredColorDescription(const ColorDescription &colorDescription) +{ + const auto &color = colorDescription.colorimetry(); + send_preferred_metadata(kwinToFrogTransferFunction(colorDescription.transferFunction()), + encodePrimary(color.red.x()), encodePrimary(color.red.y()), + encodePrimary(color.green.x()), encodePrimary(color.green.y()), + encodePrimary(color.blue.x()), encodePrimary(color.blue.y()), + encodePrimary(color.white.x()), encodePrimary(color.white.y()), + std::round(colorDescription.maxHdrHighlightBrightness()), + std::round(colorDescription.minHdrBrightness() / 0.0001), + std::round(colorDescription.maxFrameAverageBrightness())); +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_set_known_transfer_function(Resource *resource, uint32_t transfer_function) +{ + switch (transfer_function) { + case transfer_function_undefined: + case transfer_function_srgb: + case transfer_function_gamma_22: + m_transferFunction = NamedTransferFunction::sRGB; + break; + case transfer_function_st2084_pq: + m_transferFunction = NamedTransferFunction::PerceptualQuantizer; + break; + case transfer_function_scrgb_linear: + m_transferFunction = NamedTransferFunction::scRGB; + break; + } + updateColorDescription(); +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_set_known_container_color_volume(Resource *resource, uint32_t primaries) +{ + switch (primaries) { + case primaries_undefined: + case primaries_rec709: + m_colorimetry = NamedColorimetry::BT709; + break; + case primaries_rec2020: + m_colorimetry = NamedColorimetry::BT2020; + break; + } + updateColorDescription(); +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_set_render_intent(Resource *resource, uint32_t render_intent) +{ + // there's only perceptual right now, so this can be ignored +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_set_hdr_metadata(Resource *resource, + uint32_t mastering_display_primary_red_x, uint32_t mastering_display_primary_red_y, + uint32_t mastering_display_primary_green_x, uint32_t mastering_display_primary_green_y, + uint32_t mastering_display_primary_blue_x, uint32_t mastering_display_primary_blue_y, + uint32_t mastering_white_point_x, uint32_t mastering_white_point_y, + uint32_t max_display_mastering_luminance, uint32_t min_display_mastering_luminance, + uint32_t max_cll, uint32_t max_fall) +{ + m_maxPeakBrightness = max_cll; + m_maxFrameAverageBrightness = max_fall; + updateColorDescription(); +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_destroy(Resource *resource) +{ + wl_resource_destroy(resource->handle); +} + +void FrogColorManagementSurfaceV1::frog_color_managed_surface_destroy_resource(Resource *resource) +{ + delete this; +} + +void FrogColorManagementSurfaceV1::updateColorDescription() +{ + if (m_surface) { + // TODO make brightness values optional in ColorDescription + SurfaceInterfacePrivate *priv = SurfaceInterfacePrivate::get(m_surface); + priv->pending->colorDescription = ColorDescription(m_colorimetry, m_transferFunction, 0, 0, m_maxFrameAverageBrightness, m_maxPeakBrightness); + priv->pending->colorDescriptionIsSet = true; + } +} + +} + +#include "moc_frog_colormanagement_v1.cpp" diff --git a/src/wayland/frog_colormanagement_v1.h b/src/wayland/frog_colormanagement_v1.h new file mode 100644 index 0000000000..246ff01a46 --- /dev/null +++ b/src/wayland/frog_colormanagement_v1.h @@ -0,0 +1,62 @@ +/* + SPDX-FileCopyrightText: 2023 Xaver Hugl + + SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL +*/ +#pragma once + +#include "libkwineffects/colorspace.h" +#include "qwayland-server-frog-color-management-v1.h" + +#include +#include + +namespace KWin +{ + +class Display; +class SurfaceInterface; + +class FrogColorManagementV1 : public QObject, private QtWaylandServer::frog_color_management_factory_v1 +{ + Q_OBJECT +public: + explicit FrogColorManagementV1(Display *display, QObject *parent); + ~FrogColorManagementV1() override; + +private: + void frog_color_management_factory_v1_get_color_managed_surface(Resource *resource, wl_resource *surface, uint32_t callback) override; + void frog_color_management_factory_v1_destroy(Resource *resource) override; +}; + +class FrogColorManagementSurfaceV1 : public QObject, private QtWaylandServer::frog_color_managed_surface +{ + Q_OBJECT +public: + explicit FrogColorManagementSurfaceV1(SurfaceInterface *surface, wl_client *client, uint32_t id); + ~FrogColorManagementSurfaceV1() override; + + void setPreferredColorDescription(const ColorDescription &colorDescription); + +private: + void frog_color_managed_surface_set_known_transfer_function(Resource *resource, uint32_t transfer_function) override; + void frog_color_managed_surface_set_known_container_color_volume(Resource *resource, uint32_t primaries) override; + void frog_color_managed_surface_set_render_intent(Resource *resource, uint32_t render_intent) override; + void frog_color_managed_surface_set_hdr_metadata(Resource *resource, uint32_t mastering_display_primary_red_x, uint32_t mastering_display_primary_red_y, + uint32_t mastering_display_primary_green_x, uint32_t mastering_display_primary_green_y, + uint32_t mastering_display_primary_blue_x, uint32_t mastering_display_primary_blue_y, + uint32_t mastering_white_point_x, uint32_t mastering_white_point_y, + uint32_t max_display_mastering_luminance, uint32_t min_display_mastering_luminance, + uint32_t max_cll, uint32_t max_fall) override; + void frog_color_managed_surface_destroy(Resource *resource) override; + void frog_color_managed_surface_destroy_resource(Resource *resource) override; + void updateColorDescription(); + + const QPointer m_surface; + NamedTransferFunction m_transferFunction = NamedTransferFunction::sRGB; + NamedColorimetry m_colorimetry = NamedColorimetry::BT709; + float m_maxFrameAverageBrightness = 0; + float m_maxPeakBrightness = 0; +}; + +} diff --git a/src/wayland/protocols/frog-color-management-v1.xml b/src/wayland/protocols/frog-color-management-v1.xml new file mode 100644 index 0000000000..3d6c2f5d05 --- /dev/null +++ b/src/wayland/protocols/frog-color-management-v1.xml @@ -0,0 +1,356 @@ + + + + + Copyright © 2023 Joshua Ashton for Valve Software + Copyright © 2023 Xaver Hugl + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + The aim of this color management extension is to get HDR games working quickly, + and have an easy way to test implementations in the wild before the upstream + protocol is ready to be merged. + For that purpose it's intentionally limited and cut down and does not serve + all uses cases. + + + + + The color management factory singleton creates color managed surface objects. + + + + + + + + + + + + + + + + Interface for changing surface color management and HDR state. + + An implementation must: support every part of the version + of the frog_color_managed_surface interface it exposes. + Including all known enums associated with a given version. + + + + + Destroying the color managed surface resets all known color + state for the surface back to 'undefined' implementation-specific + values. + + + + + + Extended information on the transfer functions described + here can be found in the Khronos Data Format specification: + + https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + Extended information on render intents described + here can be found in ICC.1:2022: + + https://www.color.org/specification/ICC.1-2022-05.pdf + + + + + + + NOTE: On a surface with "perceptual" (default) render intent, handling of the container's color volume + is implementation-specific, and may differ between different transfer functions it is paired with: + ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's gamut + to be be more pleasing for the viewer. + Compared to scRGB Linear + 709 being treated faithfully as 709 + (including utilizing negatives out of the 709 gamut triangle) + + + + + + + Forwards HDR metadata from the client to the compositor. + + HDR Metadata Infoframe as per CTA 861.G spec. + + Usage of this HDR metadata is implementation specific and + outside of the scope of this protocol. + + + + Mastering Red Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Red Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Green Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Green Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Blue Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering Blue Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering White Point X Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Mastering White Point Y Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Max Mastering Display Luminance. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Min Mastering Display Luminance. + This value is coded as an unsigned 16-bit value in units of + 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF + represents 6.5535 cd/m2. + + + + + Max Content Light Level. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Max Frame Average Light Level. + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + + + Current preferred metadata for a surface. + The application should use this information to tone-map its buffers + to this target before committing. + + This metadata does not necessarily correspond to any physical output, but + rather what the compositor thinks would be best for a given surface. + + + + Specifies a known transfer function that corresponds to the + output the surface is targeting. + + + + + Output Red Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Red Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Green Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Green Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Blue Color Primary X Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output Blue Color Primary Y Coordinate of the Data. + + Coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output White Point X Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Output White Point Y Coordinate of the Data. + + These are coded as unsigned 16-bit values in units of + 0.00002, where 0x0000 represents zero and 0xC350 + represents 1.0000. + + + + + Max Output Luminance + The max luminance in nits that the output is capable of rendering in small areas. + Content should: not exceed this value to avoid clipping. + + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + Min Output Luminance + The min luminance that the output is capable of rendering. + Content should: not exceed this value to avoid clipping. + + This value is coded as an unsigned 16-bit value in units of + 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF + represents 6.5535 cd/m2. + + + + + Max Full Frame Luminance + The max luminance in nits that the output is capable of rendering for the + full frame sustained. + + This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + + + + + diff --git a/src/wayland/surface.cpp b/src/wayland/surface.cpp index a68672d670..7bf6d015ed 100644 --- a/src/wayland/surface.cpp +++ b/src/wayland/surface.cpp @@ -11,6 +11,7 @@ #include "contrast.h" #include "display.h" #include "fractionalscale_v1_p.h" +#include "frog_colormanagement_v1.h" #include "idleinhibit_v1_p.h" #include "linuxdmabufv1clientbuffer.h" #include "output.h" @@ -82,6 +83,9 @@ void SurfaceInterfacePrivate::addChild(SubSurfaceInterface *child) if (preferredBufferTransform.has_value()) { child->surface()->setPreferredBufferTransform(preferredBufferTransform.value()); } + if (preferredColorDescription) { + child->surface()->setPreferredColorDescription(preferredColorDescription.value()); + } Q_EMIT q->childSubSurfaceAdded(child); Q_EMIT q->childSubSurfacesChanged(); @@ -1152,6 +1156,20 @@ const ColorDescription &SurfaceInterface::colorDescription() const return d->current->colorDescription; } +void SurfaceInterface::setPreferredColorDescription(const ColorDescription &descr) +{ + d->preferredColorDescription = descr; + if (d->frogColorManagement) { + d->frogColorManagement->setPreferredColorDescription(descr); + } + for (auto child : std::as_const(d->current->subsurface.below)) { + child->surface()->setPreferredColorDescription(descr); + } + for (auto child : std::as_const(d->current->subsurface.above)) { + child->surface()->setPreferredColorDescription(descr); + } +} + void SurfaceInterface::setPreferredBufferScale(qreal scale) { if (scale == d->preferredBufferScale) { diff --git a/src/wayland/surface.h b/src/wayland/surface.h index ebdc2fb3a2..d6028213e7 100644 --- a/src/wayland/surface.h +++ b/src/wayland/surface.h @@ -374,6 +374,8 @@ public: const ColorDescription &colorDescription() const; + void setPreferredColorDescription(const ColorDescription &descr); + Q_SIGNALS: /** * This signal is emitted when the underlying wl_surface resource is about to be freed. diff --git a/src/wayland/surface_p.h b/src/wayland/surface_p.h index b8df505f9b..e9ca88274e 100644 --- a/src/wayland/surface_p.h +++ b/src/wayland/surface_p.h @@ -25,6 +25,7 @@ class ViewportInterface; class ContentTypeV1Interface; class TearingControlV1Interface; class FractionalScaleV1Interface; +class FrogColorManagementSurfaceV1; struct SurfaceState { @@ -149,6 +150,7 @@ public: OutputInterface *primaryOutput = nullptr; std::optional preferredBufferScale; std::optional preferredBufferTransform; + std::optional preferredColorDescription; LockedPointerV1Interface *lockedPointer = nullptr; ConfinedPointerV1Interface *confinedPointer = nullptr; @@ -162,6 +164,7 @@ public: FractionalScaleV1Interface *fractionalScaleExtension = nullptr; ClientConnection *client = nullptr; TearingControlV1Interface *tearing = nullptr; + FrogColorManagementSurfaceV1 *frogColorManagement = nullptr; struct { diff --git a/src/wayland_server.cpp b/src/wayland_server.cpp index dbeac54df4..77a54e4a52 100644 --- a/src/wayland_server.cpp +++ b/src/wayland_server.cpp @@ -32,6 +32,7 @@ #include "wayland/drmlease_v1.h" #include "wayland/filtered_display.h" #include "wayland/fractionalscale_v1.h" +#include "wayland/frog_colormanagement_v1.h" #include "wayland/idle.h" #include "wayland/idleinhibit_v1.h" #include "wayland/idlenotify_v1.h" @@ -521,6 +522,7 @@ bool WaylandServer::init(InitializationFlags flags) } }); + new FrogColorManagementV1(m_display, m_display); return true; } diff --git a/src/waylandwindow.cpp b/src/waylandwindow.cpp index 751ae706a7..71cb05a837 100644 --- a/src/waylandwindow.cpp +++ b/src/waylandwindow.cpp @@ -161,6 +161,7 @@ void WaylandWindow::updateClientOutputs() if (output()) { surface()->setPreferredBufferScale(output()->scale()); surface()->setPreferredBufferTransform(output()->transform()); + surface()->setPreferredColorDescription(output()->colorDescription()); } }