21struct SurfaceFormatSelectionResult {
23 std::optional<KisSurfaceColorimetry::SurfaceDescription> requestedDescription;
32 QScopedPointer<KisSurfaceColorManagerInterface>
interface;
40 SurfaceFormatSelectionResult
52 m_d->currentConfig.setOptions(options);
53 m_d->currentConfig.isHDR =
false;
59 if (
m_d->interface->isReady()) {
73 if (!
m_d->interface->isReady()) {
74 str <<
"WARNING: surface color management interface is not ready!" << Qt::endl;
83 if (!
m_d->lastErrorString.isEmpty()) {
84 str.noquote().nospace()
85 <<
"ERROR: Failed to set up color management for the surface: "
86 <<
m_d->lastErrorString
91 str <<
"Configured mode:" <<
m_d->surfaceMode << Qt::endl;
93 RenderIntent preferredIntent = Private::calculateConfigIntent(
m_d->currentConfig.options());
94 str <<
"Configured intent:" << preferredIntent <<
"supported:" <<
m_d->interface->supportsRenderIntent(preferredIntent) << Qt::endl;
96 str <<
"Actual intent:";
97 if (
m_d->interface->renderingIntent()) {
98 str << *
m_d->interface->renderingIntent() << Qt::endl;
100 str <<
"<none>" << Qt::endl;
104 str <<
"Active surface description:";
105 if (
m_d->interface->surfaceDescription()) {
107 str.noquote() <<
m_d->interface->surfaceDescription()->makeTextReport() << Qt::endl;
109 str <<
"<none>" << Qt::endl;
113 str <<
"Selected Profile:";
114 if (
m_d->currentConfig.profile) {
115 auto profile =
m_d->currentConfig.profile;
117 str << profile->name() << Qt::endl;
123 auto colVec = profile->getColorantsxyY();
129 str <<
" red: " << colR << Qt::endl;
130 str <<
" green:" << colG << Qt::endl;
131 str <<
" blue: " << colB << Qt::endl;
135 auto whiteVec = profile->getWhitePointxyY();
139 str <<
" white: " << white << Qt::endl;
144 str <<
"<none>" << Qt::endl;
147 str <<
"Compositor preferred surface description:";
148 if (
m_d->interface->preferredSurfaceDescription()) {
150 str.noquote() <<
m_d->interface->preferredSurfaceDescription()->makeTextReport() << Qt::endl;
152 str <<
"<none>" << Qt::endl;
164 if (!
m_d->interface->isReady()) {
165 str <<
"WARNING: surface color management interface is not ready!" << Qt::endl;
169 if (
m_d->interface->preferredSurfaceDescription()) {
171 str.noquote() <<
m_d->interface->preferredSurfaceDescription()->makeTextReport() << Qt::endl;
173 str <<
"<none>" << Qt::endl;
181 return m_d->interface->preferredSurfaceDescription();
188 RenderIntent intent = RenderIntent::render_intent_perceptual;
190 switch (options.first) {
197 RenderIntent::render_intent_relative_bpc :
198 RenderIntent::render_intent_relative;
202 RenderIntent::render_intent_saturation;
206 RenderIntent::render_intent_absolute;
214 if (!
m_d->interface->isReady())
return;
215 if (
surfaceMode ==
m_d->surfaceMode && options ==
m_d->currentConfig.options())
return;
241SurfaceFormatSelectionResult
242KisCanvasSurfaceColorSpaceManager::Private::
251 std::optional<SurfaceDescription> requestedDescription = SurfaceDescription();
256 auto makeKritaRec2020PQLuminance = []() {
258 luminance.minLuminance = 0;
259 luminance.referenceLuminance = 80;
260 luminance.maxLuminance = 10000;
269 requestedDescription->colorSpace.
primaries = NamedPrimaries::primaries_bt2020;
270 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_st2084_pq;
274 requestedDescription->colorSpace = compositorPreferred.
colorSpace;
277 if (std::holds_alternative<NamedTransferFunction>(requestedDescription->colorSpace.transferFunction)
278 && std::get<NamedTransferFunction>(requestedDescription->colorSpace.transferFunction)
279 == NamedTransferFunction::transfer_function_st2084_pq) {
280 requestedDescription->colorSpace.
luminance = makeKritaRec2020PQLuminance();
283 requestedDescription->colorSpace.primaries = NamedPrimaries::primaries_bt2020;
284 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_st2084_pq;
285 requestedDescription->colorSpace.luminance = makeKritaRec2020PQLuminance();
287 requestedDescription->colorSpace.primaries = NamedPrimaries::primaries_srgb;
288 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_gamma22;
291 requestedDescription->colorSpace.luminance = compositorPreferred.
colorSpace.
luminance->clipToSdr();
294 requestedDescription->colorSpace.primaries = NamedPrimaries::primaries_srgb;
295 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_ext_linear;
309 requestedDescription->colorSpace.luminance = compositorPreferred.
colorSpace.
luminance->clipToSdr();
313 if (std::holds_alternative<NamedPrimaries>(requestedDescription->colorSpace.primaries)
314 && std::get<NamedPrimaries>(requestedDescription->colorSpace.primaries) == NamedPrimaries::primaries_unknown) {
315 requestedDescription->colorSpace.primaries = NamedPrimaries::primaries_srgb;
318 if (std::holds_alternative<NamedTransferFunction>(requestedDescription->colorSpace.transferFunction)
319 && std::get<NamedTransferFunction>(requestedDescription->colorSpace.transferFunction)
320 == NamedTransferFunction::transfer_function_unknown) {
321 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_gamma22;
324 if (!this->interface->supportsSurfaceDescription(*requestedDescription)) {
326 requestedDescription->colorSpace.primaries = NamedPrimaries::primaries_srgb;
327 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_srgb;
329 if (!this->interface->supportsSurfaceDescription(*requestedDescription)) {
330 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_gamma22;
332 if (!this->interface->supportsSurfaceDescription(*requestedDescription)) {
333 QString errorMessage =
"failed to find a suitable surface format for the compositor";
334 qWarning().nospace().noquote() <<
"ERROR: " << errorMessage;
342 if (request.isValid()) {
344 request.colorPrimariesType,
345 request.transferFunction);
351 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_gamma22;
352 if (this->interface->supportsSurfaceDescription(*requestedDescription)) {
354 if (request.isValid()) {
356 request.colorPrimariesType,
357 request.transferFunction);
364 requestedDescription->colorSpace.
primaries = NamedPrimaries::primaries_srgb;
365 if (this->interface->supportsSurfaceDescription(*requestedDescription)) {
367 if (request.isValid()) {
369 request.colorPrimariesType,
370 request.transferFunction);
377 requestedDescription->colorSpace.transferFunction = NamedTransferFunction::transfer_function_srgb;
378 if (this->interface->supportsSurfaceDescription(*requestedDescription)) {
380 if (request.isValid()) {
382 request.colorPrimariesType,
383 request.transferFunction);
389 QString errorMessage =
"failed to create a profile for the compositor's preferred color space";
390 qWarning().nospace().noquote() <<
"ERROR: " << errorMessage;
391 qWarning() <<
" " <<
ppVar(compositorPreferred);
392 qWarning() <<
" " <<
ppVar(*requestedDescription);
396 return {profile, requestedDescription, {}};
406 RenderIntent preferredIntent =
407 Private::calculateConfigIntent(newOptions);
409 if (!
m_d->interface->supportsRenderIntent(preferredIntent)) {
410 qWarning() <<
"WARNING: failed to set user preferred rendering"
411 <<
"intent for the surface, intent \""
412 << preferredIntent <<
"\" is unsupported, falling back to \"perceptual\"";
414 preferredIntent = RenderIntent::render_intent_perceptual;
420 std::optional<SurfaceDescription> requestedDescription;
425 m_d->lastErrorString.clear();
427 const auto compositorPreferred =
m_d->interface->preferredSurfaceDescription();
430 auto result =
m_d->selectSurfaceDescription(
m_d->surfaceMode, *compositorPreferred);
431 profile = result.profile;
432 requestedDescription = result.requestedDescription;
433 m_d->lastErrorString = result.errorMessage;
439 if (
m_d->interface->surfaceDescription() != requestedDescription ||
440 m_d->interface->renderingIntent() != preferredIntent) {
442 if (requestedDescription) {
443 auto future =
m_d->interface->setSurfaceDescription(*requestedDescription, preferredIntent);
445 if (!result.isValid() || !result.result()) {
446 QString errorMessage =
"failed to set color space for the surface, setSurfaceDescription() returned false";
447 m_d->lastErrorString = errorMessage;
448 qWarning().nospace().noquote() <<
"ERROR: " << errorMessage;
452 m_d->interface->unsetSurfaceDescription();
456 const bool requestedDescriptionIsHDR = requestedDescription && requestedDescription->colorSpace.isHDR();
459 newDisplayConfig.
profile = profile;
461 newDisplayConfig.
isHDR = requestedDescriptionIsHDR;
467 if (
m_d->currentConfig != newDisplayConfig) {
468 m_d->currentConfig = newDisplayConfig;
475 return m_d->interface->isReady();
480 return m_d->currentConfig;
KisDisplayConfig This class keeps track of the color management configuration for image to display....
void setOptions(const Options &options)
std::pair< KoColorConversionTransformation::Intent, KoColorConversionTransformation::ConversionFlags > Options
const KoColorProfile * profile
void sigReadyChanged(bool value)
void sigPreferredSurfaceDescriptionChanged(const KisSurfaceColorimetry::SurfaceDescription &desc)
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
#define INTENT_ABSOLUTE_COLORIMETRIC
#define INTENT_PERCEPTUAL
#define INTENT_RELATIVE_COLORIMETRIC
#define INTENT_SATURATION
PigmentProfileRequest colorSpaceToRequest(ColorSpace cs)
QScopedPointer< KisSurfaceColorManagerInterface > interface
std::optional< KisSurfaceColorimetry::SurfaceDescription > currentSurfaceDescription() const
KisConfig::CanvasSurfaceMode surfaceMode
KisCanvasSurfaceColorSpaceManager(KisSurfaceColorManagerInterface *interface, const KisConfig::CanvasSurfaceMode surfaceMode, const KisDisplayConfig::Options &options, QObject *parent=nullptr)
void sigDisplayConfigChanged(const KisDisplayConfig &config)
void slotInterfacePreferredDescriptionChanged()
KisDisplayConfig currentConfig
QString osPreferredColorSpaceReport() const
Private(KisSurfaceColorManagerInterface *interface)
QScopedPointer< Private > m_d
std::optional< KisSurfaceColorimetry::RenderIntent > proofingIntentOverride
void reinitializeSurfaceDescription(const KisDisplayConfig::Options &newOptions)
SurfaceFormatSelectionResult selectSurfaceDescription(KisConfig::CanvasSurfaceMode surfaceMode, const KisSurfaceColorimetry::SurfaceDescription &compositorPreferred)
static KisSurfaceColorimetry::RenderIntent calculateConfigIntent(const KisDisplayConfig::Options &options)
void slotInterfaceReadyChanged(bool isReady)
KisDisplayConfig displayConfig() const
QString colorManagementReport() const
~KisCanvasSurfaceColorSpaceManager()
void setDisplayConfigOptions(const KisConfig::CanvasSurfaceMode surfaceMode, const KisDisplayConfig::Options &options)
std::optional< Luminance > luminance
static QString getTransferCharacteristicName(TransferCharacteristics curve)
getTransferCharacteristicName
static QString getColorPrimariesName(ColorPrimaries primaries)
getColorPrimariesName
const KoColorProfile * profileFor(const QVector< double > &colorants, ColorPrimaries colorPrimaries, TransferCharacteristics transferFunction) const
profileFor tries to find the profile that matches these characteristics, if no such profile is found,...
static KoColorSpaceRegistry * instance()
const KoColorProfile * p709SRGBProfile() const