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// Qt-Security score:significant reason:default
4
7
8#include <QDebug>
9
10#include <unistd.h>
11
12QT_BEGIN_NAMESPACE
13
14namespace QtWaylandClient {
15
16ColorManager::ColorManager(struct ::wl_registry *registry, uint32_t id, int version)
17 : QtWayland::wp_color_manager_v1(registry, id, version)
18{
19}
20
22{
23 destroy();
24}
25
27{
28 switch (feature) {
29 case feature_icc_v2_v4:
30 mFeatures |= Feature::ICC;
31 break;
32 case feature_parametric:
33 mFeatures |= Feature::Parametric;
34 break;
35 case feature_set_primaries:
36 mFeatures |= Feature::SetPrimaries;
37 break;
38 case feature_set_tf_power:
39 mFeatures |= Feature::PowerTransferFunction;
40 break;
41 case feature_set_luminances:
42 mFeatures |= Feature::SetLuminances;
43 break;
44 case feature_set_mastering_display_primaries:
45 mFeatures |= Feature::SetMasteringDisplayPrimaries;
46 break;
47 case feature_extended_target_volume:
48 mFeatures |= Feature::ExtendedTargetVolume;
49 break;
50 }
51}
52
54{
55 mPrimaries.push_back(QtWayland::wp_color_manager_v1::primaries(primaries));
56}
57
59{
60 mTransferFunctions.push_back(QtWayland::wp_color_manager_v1::transfer_function(transferFunction));
61}
62
64{
65 return mFeatures;
66}
67
68bool ColorManager::supportsNamedPrimary(QtWayland::wp_color_manager_v1::primaries primaries) const
69{
70 return mPrimaries.contains(primaries);
71}
72
73bool ColorManager::supportsTransferFunction(QtWayland::wp_color_manager_v1::transfer_function transferFunction) const
74{
75 return mTransferFunctions.contains(transferFunction);
76}
77
79{
80 if (!(mFeatures & Feature::Parametric))
81 return nullptr;
82
83 constexpr std::array primaryMapping = {
84 std::make_pair(QColorSpace::Primaries::SRgb, primaries_srgb),
85 std::make_pair(QColorSpace::Primaries::AdobeRgb, primaries_adobe_rgb),
86 std::make_pair(QColorSpace::Primaries::DciP3D65, primaries_display_p3),
87 std::make_pair(QColorSpace::Primaries::Bt2020, primaries_bt2020),
88 };
89 const auto primary = std::find_if(primaryMapping.begin(), primaryMapping.end(), [&colorspace](const auto &pair) {
90 return pair.first == colorspace.primaries();
91 });
92 if (!(supportedFeatures() & Feature::SetPrimaries) && (primary == primaryMapping.end() || !supportsNamedPrimary(primary->second)))
93 return nullptr;
94
95 constexpr std::array tfMapping = {
96 std::make_pair(QColorSpace::TransferFunction::Linear, transfer_function_ext_linear),
97 std::make_pair(QColorSpace::TransferFunction::SRgb, transfer_function_gamma22),
98 std::make_pair(QColorSpace::TransferFunction::St2084, transfer_function_st2084_pq),
99 std::make_pair(QColorSpace::TransferFunction::Hlg, transfer_function_hlg),
100 };
101 const auto tfIt = std::find_if(tfMapping.begin(), tfMapping.end(), [&colorspace](const auto &pair) {
102 return pair.first == colorspace.transferFunction();
103 });
104 auto transferFunction = tfIt == tfMapping.end() ? std::nullopt : std::make_optional(tfIt->second);
105 if (colorspace.transferFunction() == QColorSpace::TransferFunction::Gamma) {
106 if (qFuzzyCompare(colorspace.gamma(), 2.2f) && supportsTransferFunction(transfer_function_gamma22))
107 transferFunction = transfer_function_gamma22;
108 else if (qFuzzyCompare(colorspace.gamma(), 2.8f) && supportsTransferFunction(transfer_function_gamma28))
109 transferFunction = transfer_function_gamma28;
110 if (!transferFunction && !(mFeatures & Feature::PowerTransferFunction)) {
111 if (qFuzzyCompare(colorspace.gamma(), 563.0f / 256.0f) && supportsTransferFunction(transfer_function_gamma22)) {
112 // If power tf is not supported, we can use Adobe RGB gamma approximation
113 transferFunction = transfer_function_gamma22;
114 } else {
115 return nullptr;
116 }
117 }
118 } else if (!transferFunction || !supportsTransferFunction(*transferFunction)) {
119 return nullptr;
120 }
121
122 auto creator = create_parametric_creator();
123 if (primary != primaryMapping.end()) {
124 wp_image_description_creator_params_v1_set_primaries_named(creator, primary->second);
125 } else {
126 const auto primaries = colorspace.primaryPoints();
127 wp_image_description_creator_params_v1_set_primaries(creator,
128 std::round(1'000'000 * primaries.redPoint.x()), std::round(1'000'000 * primaries.redPoint.y()),
129 std::round(1'000'000 * primaries.greenPoint.x()), std::round(1'000'000 * primaries.greenPoint.y()),
130 std::round(1'000'000 * primaries.bluePoint.x()), std::round(1'000'000 * primaries.bluePoint.y()),
131 std::round(1'000'000 * primaries.whitePoint.x()), std::round(1'000'000 * primaries.whitePoint.y())
132 );
133 }
134 if (transferFunction) {
135 wp_image_description_creator_params_v1_set_tf_named(creator, *transferFunction);
136 } else {
137 Q_ASSERT(colorspace.transferFunction() == QColorSpace::TransferFunction::Gamma);
138 wp_image_description_creator_params_v1_set_tf_power(creator, std::round(colorspace.gamma() * 10'000));
139 }
140 return std::make_unique<ImageDescription>(wp_image_description_creator_params_v1_create(creator));
141}
142
143ImageDescriptionInfo::ImageDescriptionInfo(ImageDescription *descr)
144 : QtWayland::wp_image_description_info_v1(descr->get_information())
145{
146}
147
149{
150 wp_image_description_info_v1_destroy(object());
151}
152
154{
155 Q_EMIT done();
156}
157
159{
160 Q_UNUSED(icc_size)
161 close(icc);
162}
163
164void ImageDescriptionInfo::wp_image_description_info_v1_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)
165{
166 mContainerRed = QPointF(r_x, r_y) / 1'000'000.0;
167 mContainerGreen = QPointF(g_x, g_y) / 1'000'000.0;
168 mContainerBlue = QPointF(b_x, b_y) / 1'000'000.0;
169 mContainerWhite = QPointF(w_x, w_y) / 1'000'000.0;
170}
171
173{
174 mTransferFunction = transferFunction;
175}
176
177void ImageDescriptionInfo::wp_image_description_info_v1_luminances(uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum)
178{
179 mMinLuminance = min_lum / 10'000.0;
180 mMaxLuminance = max_lum;
181 mReferenceLuminance = reference_lum;
182}
183
184void ImageDescriptionInfo::wp_image_description_info_v1_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)
185{
186 mTargetRed = QPointF(r_x, r_y) / 1'000'000.0;
187 mTargetGreen = QPointF(g_x, g_y) / 1'000'000.0;
188 mTargetBlue = QPointF(b_x, b_y) / 1'000'000.0;
189 mTargetWhite = QPointF(w_x, w_y) / 1'000'000.0;
190}
191
193{
194 mTargetMinLuminance = min_lum / 10'000.0;
195 mTargetMaxLuminance = max_lum;
196}
197
198ImageDescription::ImageDescription(::wp_image_description_v1 *descr)
199 : QtWayland::wp_image_description_v1(descr)
200{
201}
202
204{
205 wp_image_description_v1_destroy(object());
206}
207
208void ImageDescription::wp_image_description_v1_failed(uint32_t cause, const QString &msg)
209{
210 Q_UNUSED(cause);
211 qCWarning(lcQpaWayland) << "image description failed!" << msg;
212 // TODO handle this, somehow
213 // maybe fall back to the previous or preferred image description
214}
215
217{
218 Q_UNUSED(identity);
219 Q_EMIT ready();
220}
221
222ColorManagementFeedback::ColorManagementFeedback(::wp_color_management_surface_feedback_v1 *obj)
223 : QtWayland::wp_color_management_surface_feedback_v1(obj)
224 , mPreferred(std::make_unique<ImageDescription>(get_preferred()))
225{
226}
227
229{
230 wp_color_management_surface_feedback_v1_destroy(object());
231}
232
234{
235 Q_UNUSED(identity);
236 mPreferred = std::make_unique<ImageDescription>(get_preferred());
237 mPendingPreferredInfo = std::make_unique<ImageDescriptionInfo>(mPreferred.get());
238 connect(mPendingPreferredInfo.get(), &ImageDescriptionInfo::done, this, &ColorManagementFeedback::preferredChanged);
239}
240
241void ColorManagementFeedback::handlePreferredDone()
242{
243 mPreferredInfo = std::move(mPendingPreferredInfo);
244}
245
246ColorManagementSurface::ColorManagementSurface(::wp_color_management_surface_v1 *obj)
247 : QtWayland::wp_color_management_surface_v1(obj)
248{
249}
250
252{
253 wp_color_management_surface_v1_destroy(object());
254}
255
257{
258 if (descr)
259 wp_color_management_surface_v1_set_image_description(object(), descr->object(), QtWayland::wp_color_manager_v1::render_intent::render_intent_perceptual);
260 else
261 wp_color_management_surface_v1_unset_image_description(object());
262}
263
264}
265
266QT_END_NAMESPACE
267
268#include "moc_qwaylandcolormanagement_p.cpp"
void wp_color_management_surface_feedback_v1_preferred_changed(uint32_t identity) override
void wp_color_manager_v1_supported_tf_named(uint32_t transferFunction) override
void wp_color_manager_v1_supported_primaries_named(uint32_t primaries) override
void wp_color_manager_v1_supported_feature(uint32_t feature) override
std::unique_ptr< ImageDescription > createImageDescription(const QColorSpace &colorspace)
bool supportsTransferFunction(QtWayland::wp_color_manager_v1::transfer_function transferFunction) const
bool supportsNamedPrimary(QtWayland::wp_color_manager_v1::primaries primaries) const
void wp_image_description_info_v1_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 wp_image_description_info_v1_tf_named(uint32_t transferFunction) override
void wp_image_description_info_v1_icc_file(int32_t icc, uint32_t icc_size) override
void wp_image_description_info_v1_target_luminance(uint32_t min_lum, uint32_t max_lum) override
void wp_image_description_info_v1_luminances(uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) override
void wp_image_description_info_v1_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 wp_image_description_v1_failed(uint32_t cause, const QString &msg) override
void wp_image_description_v1_ready(uint32_t identity) override