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::wp_color_manager_v1(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::wp_color_manager_v1::primaries(primaries));
55}
56
58{
59 mTransferFunctions.push_back(QtWayland::wp_color_manager_v1::transfer_function(transferFunction));
60}
61
63{
64 return mFeatures;
65}
66
67bool ColorManager::supportsNamedPrimary(QtWayland::wp_color_manager_v1::primaries primaries) const
68{
69 return mPrimaries.contains(primaries);
70}
71
72bool ColorManager::supportsTransferFunction(QtWayland::wp_color_manager_v1::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_ext_linear),
96 std::make_pair(QColorSpace::TransferFunction::SRgb, transfer_function_gamma22),
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 if (qFuzzyCompare(colorspace.gamma(), 563.0f / 256.0f) && supportsTransferFunction(transfer_function_gamma22)) {
111 // If power tf is not supported, we can use Adobe RGB gamma approximation
112 transferFunction = transfer_function_gamma22;
113 } else {
114 return nullptr;
115 }
116 }
117 } else if (!transferFunction || !supportsTransferFunction(*transferFunction)) {
118 return nullptr;
119 }
120
121 auto creator = create_parametric_creator();
122 if (primary != primaryMapping.end()) {
123 wp_image_description_creator_params_v1_set_primaries_named(creator, primary->second);
124 } else {
125 const auto primaries = colorspace.primaryPoints();
126 wp_image_description_creator_params_v1_set_primaries(creator,
127 std::round(1'000'000 * primaries.redPoint.x()), std::round(1'000'000 * primaries.redPoint.y()),
128 std::round(1'000'000 * primaries.greenPoint.x()), std::round(1'000'000 * primaries.greenPoint.y()),
129 std::round(1'000'000 * primaries.bluePoint.x()), std::round(1'000'000 * primaries.bluePoint.y()),
130 std::round(1'000'000 * primaries.whitePoint.x()), std::round(1'000'000 * primaries.whitePoint.y())
131 );
132 }
133 if (transferFunction) {
134 wp_image_description_creator_params_v1_set_tf_named(creator, *transferFunction);
135 } else {
136 Q_ASSERT(colorspace.transferFunction() == QColorSpace::TransferFunction::Gamma);
137 wp_image_description_creator_params_v1_set_tf_power(creator, std::round(colorspace.gamma() * 10'000));
138 }
139 return std::make_unique<ImageDescription>(wp_image_description_creator_params_v1_create(creator));
140}
141
142ImageDescriptionInfo::ImageDescriptionInfo(ImageDescription *descr)
143 : QtWayland::wp_image_description_info_v1(descr->get_information())
144{
145}
146
148{
149 wp_image_description_info_v1_destroy(object());
150}
151
153{
154 Q_EMIT done();
155}
156
158{
159 Q_UNUSED(icc_size)
160 close(icc);
161}
162
163void 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)
164{
165 mContainerRed = QPointF(r_x, r_y) / 1'000'000.0;
166 mContainerGreen = QPointF(g_x, g_y) / 1'000'000.0;
167 mContainerBlue = QPointF(b_x, b_y) / 1'000'000.0;
168 mContainerWhite = QPointF(w_x, w_y) / 1'000'000.0;
169}
170
172{
173 mTransferFunction = transferFunction;
174}
175
176void ImageDescriptionInfo::wp_image_description_info_v1_luminances(uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum)
177{
178 mMinLuminance = min_lum / 10'000.0;
179 mMaxLuminance = max_lum;
180 mReferenceLuminance = reference_lum;
181}
182
183void 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)
184{
185 mTargetRed = QPointF(r_x, r_y) / 1'000'000.0;
186 mTargetGreen = QPointF(g_x, g_y) / 1'000'000.0;
187 mTargetBlue = QPointF(b_x, b_y) / 1'000'000.0;
188 mTargetWhite = QPointF(w_x, w_y) / 1'000'000.0;
189}
190
192{
193 mTargetMinLuminance = min_lum / 10'000.0;
194 mTargetMaxLuminance = max_lum;
195}
196
197ImageDescription::ImageDescription(::wp_image_description_v1 *descr)
198 : QtWayland::wp_image_description_v1(descr)
199{
200}
201
203{
204 wp_image_description_v1_destroy(object());
205}
206
207void ImageDescription::wp_image_description_v1_failed(uint32_t cause, const QString &msg)
208{
209 Q_UNUSED(cause);
210 qCWarning(lcQpaWayland) << "image description failed!" << msg;
211 // TODO handle this, somehow
212 // maybe fall back to the previous or preferred image description
213}
214
216{
217 Q_UNUSED(identity);
218 Q_EMIT ready();
219}
220
221ColorManagementFeedback::ColorManagementFeedback(::wp_color_management_surface_feedback_v1 *obj)
222 : QtWayland::wp_color_management_surface_feedback_v1(obj)
223 , mPreferred(std::make_unique<ImageDescription>(get_preferred()))
224{
225}
226
228{
229 wp_color_management_surface_feedback_v1_destroy(object());
230}
231
233{
234 Q_UNUSED(identity);
235 mPreferred = std::make_unique<ImageDescription>(get_preferred());
236 mPendingPreferredInfo = std::make_unique<ImageDescriptionInfo>(mPreferred.get());
237 connect(mPendingPreferredInfo.get(), &ImageDescriptionInfo::done, this, &ColorManagementFeedback::preferredChanged);
238}
239
240void ColorManagementFeedback::handlePreferredDone()
241{
242 mPreferredInfo = std::move(mPendingPreferredInfo);
243}
244
245ColorManagementSurface::ColorManagementSurface(::wp_color_management_surface_v1 *obj)
246 : QtWayland::wp_color_management_surface_v1(obj)
247{
248}
249
251{
252 wp_color_management_surface_v1_destroy(object());
253}
254
256{
257 if (descr)
258 wp_color_management_surface_v1_set_image_description(object(), descr->object(), QtWayland::wp_color_manager_v1::render_intent::render_intent_perceptual);
259 else
260 wp_color_management_surface_v1_unset_image_description(object());
261}
262
263}
264
265QT_END_NAMESPACE
266
267#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