Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandcolormanagement.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <QDebug>
8
9#include <unistd.h>
10
11QT_BEGIN_NAMESPACE
12
13namespace QtWaylandClient {
14
15ColorManager::ColorManager(struct ::wl_registry *registry, uint32_t id, int version)
16 : QtWayland::xx_color_manager_v4(registry, id, version)
17{
18}
19
21{
22 destroy();
23}
24
26{
27 switch (feature) {
28 case feature_icc_v2_v4:
29 mFeatures |= Feature::ICC;
30 break;
31 case feature_parametric:
32 mFeatures |= Feature::Parametric;
33 break;
34 case feature_set_primaries:
35 mFeatures |= Feature::SetPrimaries;
36 break;
37 case feature_set_tf_power:
38 mFeatures |= Feature::PowerTransferFunction;
39 break;
40 case feature_set_luminances:
41 mFeatures |= Feature::SetLuminances;
42 break;
43 case feature_set_mastering_display_primaries:
44 mFeatures |= Feature::SetMasteringDisplayPrimaries;
45 break;
46 case feature_extended_target_volume:
47 mFeatures |= Feature::ExtendedTargetVolume;
48 break;
49 }
50}
51
53{
54 mPrimaries.push_back(QtWayland::xx_color_manager_v4::primaries(primaries));
55}
56
58{
59 mTransferFunctions.push_back(QtWayland::xx_color_manager_v4::transfer_function(transferFunction));
60}
61
63{
64 return mFeatures;
65}
66
67bool ColorManager::supportsNamedPrimary(QtWayland::xx_color_manager_v4::primaries primaries) const
68{
69 return mPrimaries.contains(primaries);
70}
71
72bool ColorManager::supportsTransferFunction(QtWayland::xx_color_manager_v4::transfer_function transferFunction) const
73{
74 return mTransferFunctions.contains(transferFunction);
75}
76
78{
79 if (!(mFeatures & Feature::Parametric))
80 return nullptr;
81
82 constexpr std::array primaryMapping = {
83 std::make_pair(QColorSpace::Primaries::SRgb, primaries_srgb),
84 std::make_pair(QColorSpace::Primaries::AdobeRgb, primaries_adobe_rgb),
85 std::make_pair(QColorSpace::Primaries::DciP3D65, primaries_display_p3),
86 std::make_pair(QColorSpace::Primaries::Bt2020, primaries_bt2020),
87 };
88 const auto primary = std::find_if(primaryMapping.begin(), primaryMapping.end(), [&colorspace](const auto &pair) {
89 return pair.first == colorspace.primaries();
90 });
91 if (!(supportedFeatures() & Feature::SetPrimaries) && (primary == primaryMapping.end() || !supportsNamedPrimary(primary->second)))
92 return nullptr;
93
94 constexpr std::array tfMapping = {
95 std::make_pair(QColorSpace::TransferFunction::Linear, transfer_function_linear),
96 std::make_pair(QColorSpace::TransferFunction::SRgb, transfer_function_srgb),
97 std::make_pair(QColorSpace::TransferFunction::St2084, transfer_function_st2084_pq),
98 std::make_pair(QColorSpace::TransferFunction::Hlg, transfer_function_hlg),
99 };
100 const auto tfIt = std::find_if(tfMapping.begin(), tfMapping.end(), [&colorspace](const auto &pair) {
101 return pair.first == colorspace.transferFunction();
102 });
103 auto transferFunction = tfIt == tfMapping.end() ? std::nullopt : std::make_optional(tfIt->second);
104 if (colorspace.transferFunction() == QColorSpace::TransferFunction::Gamma) {
105 if (qFuzzyCompare(colorspace.gamma(), 2.2f) && supportsTransferFunction(transfer_function_gamma22))
106 transferFunction = transfer_function_gamma22;
107 else if (qFuzzyCompare(colorspace.gamma(), 2.8f) && supportsTransferFunction(transfer_function_gamma28))
108 transferFunction = transfer_function_gamma28;
109 if (!transferFunction && !(mFeatures & Feature::PowerTransferFunction))
110 return nullptr;
111 } else if (!transferFunction) {
112 return nullptr;
113 }
114
115 auto creator = new_parametric_creator();
116 if (primary != primaryMapping.end()) {
117 xx_image_description_creator_params_v4_set_primaries_named(creator, primary->second);
118 } else {
119 const auto primaries = colorspace.primaryPoints();
120 xx_image_description_creator_params_v4_set_primaries(creator,
121 std::round(10'000 * primaries.redPoint.x()), std::round(10'000 * primaries.redPoint.y()),
122 std::round(10'000 * primaries.greenPoint.x()), std::round(10'000 * primaries.greenPoint.y()),
123 std::round(10'000 * primaries.bluePoint.x()), std::round(10'000 * primaries.bluePoint.y()),
124 std::round(10'000 * primaries.whitePoint.x()), std::round(10'000 * primaries.whitePoint.y())
125 );
126 }
127 if (transferFunction) {
128 xx_image_description_creator_params_v4_set_tf_named(creator, *transferFunction);
129 } else {
130 Q_ASSERT(colorspace.transferFunction() == QColorSpace::TransferFunction::Gamma);
131 xx_image_description_creator_params_v4_set_tf_power(creator, std::round(colorspace.gamma() * 10'000));
132 }
133 return std::make_unique<ImageDescription>(xx_image_description_creator_params_v4_create(creator));
134}
135
136ImageDescriptionInfo::ImageDescriptionInfo(ImageDescription *descr)
137 : QtWayland::xx_image_description_info_v4(descr->get_information())
138{
139}
140
142{
143 xx_image_description_info_v4_destroy(object());
144}
145
147{
148 Q_EMIT done();
149}
150
152{
153 Q_UNUSED(icc_size)
154 close(icc);
155}
156
157void ImageDescriptionInfo::xx_image_description_info_v4_primaries(int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y)
158{
159 mContainerRed = QPointF(r_x, r_y) / 10'000.0;
160 mContainerGreen = QPointF(g_x, g_y) / 10'000.0;
161 mContainerBlue = QPointF(b_x, b_y) / 10'000.0;
162 mContainerWhite = QPointF(w_x, w_y) / 10'000.0;
163}
164
166{
167 mTransferFunction = transferFunction;
168}
169
170void ImageDescriptionInfo::xx_image_description_info_v4_luminances(uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum)
171{
172 mMinLuminance = min_lum / 10'000.0;
173 mMaxLuminance = max_lum;
174 mReferenceLuminance = reference_lum;
175}
176
177void ImageDescriptionInfo::xx_image_description_info_v4_target_primaries(int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y)
178{
179 mTargetRed = QPointF(r_x, r_y) / 10'000.0;
180 mTargetGreen = QPointF(g_x, g_y) / 10'000.0;
181 mTargetBlue = QPointF(b_x, b_y) / 10'000.0;
182 mTargetWhite = QPointF(w_x, w_y) / 10'000.0;
183}
184
186{
187 mTargetMinLuminance = min_lum / 10'000.0;
188 mTargetMaxLuminance = max_lum;
189}
190
191ImageDescription::ImageDescription(::xx_image_description_v4 *descr)
192 : QtWayland::xx_image_description_v4(descr)
193{
194}
195
197{
198 xx_image_description_v4_destroy(object());
199}
200
201void ImageDescription::xx_image_description_v4_failed(uint32_t cause, const QString &msg)
202{
203 Q_UNUSED(cause);
204 qCWarning(lcQpaWayland) << "image description failed!" << msg;
205 // TODO handle this, somehow
206 // maybe fall back to the previous or preferred image description
207}
208
210{
211 Q_UNUSED(identity);
212 Q_EMIT ready();
213}
214
215ColorManagementFeedback::ColorManagementFeedback(::xx_color_management_feedback_surface_v4 *obj)
216 : QtWayland::xx_color_management_feedback_surface_v4(obj)
217 , mPreferred(std::make_unique<ImageDescription>(get_preferred()))
218{
219}
220
222{
223 xx_color_management_feedback_surface_v4_destroy(object());
224}
225
227{
228 mPreferred = std::make_unique<ImageDescription>(get_preferred());
229 mPendingPreferredInfo = std::make_unique<ImageDescriptionInfo>(mPreferred.get());
230 connect(mPendingPreferredInfo.get(), &ImageDescriptionInfo::done, this, &ColorManagementFeedback::preferredChanged);
231}
232
233void ColorManagementFeedback::handlePreferredDone()
234{
235 mPreferredInfo = std::move(mPendingPreferredInfo);
236}
237
238ColorManagementSurface::ColorManagementSurface(::xx_color_management_surface_v4 *obj)
239 : QtWayland::xx_color_management_surface_v4(obj)
240{
241}
242
244{
245 xx_color_management_surface_v4_destroy(object());
246}
247
249{
250 if (descr)
251 xx_color_management_surface_v4_set_image_description(object(), descr->object(), QtWayland::xx_color_manager_v4::render_intent::render_intent_perceptual);
252 else
253 xx_color_management_surface_v4_unset_image_description(object());
254}
255
256}
257
258QT_END_NAMESPACE
259
260#include "moc_qwaylandcolormanagement_p.cpp"
void xx_color_manager_v4_supported_tf_named(uint32_t transferFunction) override
bool supportsTransferFunction(QtWayland::xx_color_manager_v4::transfer_function transferFunction) const
std::unique_ptr< ImageDescription > createImageDescription(const QColorSpace &colorspace)
void xx_color_manager_v4_supported_primaries_named(uint32_t primaries) override
void xx_color_manager_v4_supported_feature(uint32_t feature) override
bool supportsNamedPrimary(QtWayland::xx_color_manager_v4::primaries primaries) const
void xx_image_description_info_v4_icc_file(int32_t icc, uint32_t icc_size) override
void xx_image_description_info_v4_tf_named(uint32_t transferFunction) override
void xx_image_description_info_v4_target_primaries(int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) override
void xx_image_description_info_v4_luminances(uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) override
void xx_image_description_info_v4_primaries(int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) override
void xx_image_description_info_v4_target_luminance(uint32_t min_lum, uint32_t max_lum) override
void xx_image_description_v4_failed(uint32_t cause, const QString &msg) override
void xx_image_description_v4_ready(uint32_t identity) override