2021-11-29 14:44:56 -05:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
|
|
|
* Copyright (C) 2011-2013 Richard Hughes <richard@hughsie.com>
|
|
|
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
|
|
|
* Copyright (C) 2021 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "backends/meta-color-profile.h"
|
|
|
|
|
|
|
|
#include <colord.h>
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
#include "backends/meta-color-manager-private.h"
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
READY,
|
|
|
|
|
|
|
|
N_SIGNALS
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
|
2021-11-29 14:44:56 -05:00
|
|
|
struct _MetaColorProfile
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
|
|
|
|
MetaColorManager *color_manager;
|
|
|
|
|
|
|
|
CdIcc *cd_icc;
|
|
|
|
GBytes *bytes;
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
MetaColorCalibration *calibration;
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
char *cd_profile_id;
|
2021-12-01 12:57:52 -05:00
|
|
|
gboolean is_owner;
|
2021-11-30 05:56:31 -05:00
|
|
|
CdProfile *cd_profile;
|
|
|
|
GCancellable *cancellable;
|
2021-12-01 12:57:52 -05:00
|
|
|
guint notify_ready_id;
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
gboolean is_ready;
|
2021-11-29 14:44:56 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaColorProfile, meta_color_profile,
|
|
|
|
G_TYPE_OBJECT)
|
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GMainLoop *loop;
|
|
|
|
CdProfile *cd_profile;
|
|
|
|
GError *error;
|
|
|
|
} FindProfileData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_find_profile (GObject *source_object,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
CdClient *cd_client = CD_CLIENT (source_object);
|
|
|
|
FindProfileData *data = user_data;
|
|
|
|
|
|
|
|
data->cd_profile = cd_client_find_profile_finish (cd_client, res,
|
|
|
|
&data->error);
|
|
|
|
g_main_loop_quit (data->loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
static CdProfile *
|
|
|
|
find_profile_sync (CdClient *cd_client,
|
|
|
|
const char *cd_profile_id,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
g_autoptr (GMainContext) main_context = NULL;
|
|
|
|
g_autoptr (GMainLoop) main_loop = NULL;
|
|
|
|
FindProfileData data = {};
|
|
|
|
|
|
|
|
main_context = g_main_context_new ();
|
|
|
|
main_loop = g_main_loop_new (main_context, FALSE);
|
|
|
|
g_main_context_push_thread_default (main_context);
|
|
|
|
|
|
|
|
data = (FindProfileData) {
|
|
|
|
.loop = main_loop,
|
|
|
|
};
|
|
|
|
cd_client_find_profile (cd_client, cd_profile_id, NULL,
|
|
|
|
on_find_profile,
|
|
|
|
&data);
|
|
|
|
g_main_loop_run (main_loop);
|
|
|
|
|
|
|
|
g_main_context_pop_thread_default (main_context);
|
|
|
|
|
|
|
|
if (data.error)
|
|
|
|
g_propagate_error (error, data.error);
|
|
|
|
return data.cd_profile;
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:44:56 -05:00
|
|
|
static void
|
|
|
|
meta_color_profile_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaColorProfile *color_profile = META_COLOR_PROFILE (object);
|
2021-11-30 05:56:31 -05:00
|
|
|
MetaColorManager *color_manager = color_profile->color_manager;
|
|
|
|
CdClient *cd_client = meta_color_manager_get_cd_client (color_manager);
|
2021-11-29 14:44:56 -05:00
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
g_cancellable_cancel (color_profile->cancellable);
|
|
|
|
g_clear_object (&color_profile->cancellable);
|
2021-12-01 12:57:52 -05:00
|
|
|
g_clear_handle_id (&color_profile->notify_ready_id, g_source_remove);
|
2021-11-30 05:56:31 -05:00
|
|
|
|
2021-12-01 12:57:52 -05:00
|
|
|
if (color_profile->is_owner)
|
2021-11-30 05:56:31 -05:00
|
|
|
{
|
2021-12-01 12:57:52 -05:00
|
|
|
CdProfile *cd_profile;
|
2021-11-30 05:56:31 -05:00
|
|
|
|
2021-12-01 12:57:52 -05:00
|
|
|
cd_profile = color_profile->cd_profile;
|
2022-09-13 12:18:00 -04:00
|
|
|
if (!cd_profile && !color_profile->is_ready)
|
2021-11-30 05:56:31 -05:00
|
|
|
{
|
2021-12-01 12:57:52 -05:00
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
cd_profile = find_profile_sync (cd_client,
|
|
|
|
color_profile->cd_profile_id,
|
|
|
|
&error);
|
|
|
|
if (!cd_profile &&
|
2022-09-13 12:19:40 -04:00
|
|
|
!g_error_matches (error,
|
|
|
|
CD_CLIENT_ERROR,
|
|
|
|
CD_CLIENT_ERROR_NOT_FOUND))
|
2021-12-01 12:57:52 -05:00
|
|
|
{
|
|
|
|
g_warning ("Failed to find colord profile %s: %s",
|
|
|
|
color_profile->cd_profile_id,
|
|
|
|
error->message);
|
|
|
|
}
|
2021-11-30 05:56:31 -05:00
|
|
|
}
|
|
|
|
|
2021-12-01 12:57:52 -05:00
|
|
|
if (cd_profile)
|
|
|
|
cd_client_delete_profile (cd_client, cd_profile, NULL, NULL, NULL);
|
|
|
|
}
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
g_clear_pointer (&color_profile->cd_profile_id, g_free);
|
2021-11-29 14:44:56 -05:00
|
|
|
g_clear_object (&color_profile->cd_icc);
|
|
|
|
g_clear_pointer (&color_profile->bytes, g_bytes_unref);
|
2021-11-30 05:56:31 -05:00
|
|
|
g_clear_object (&color_profile->cd_profile);
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
g_clear_pointer (&color_profile->calibration, meta_color_calibration_free);
|
2021-11-29 14:44:56 -05:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_color_profile_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_color_profile_class_init (MetaColorProfileClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_color_profile_finalize;
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
signals[READY] =
|
|
|
|
g_signal_new ("ready",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST, 0,
|
|
|
|
NULL, NULL, NULL,
|
2022-09-13 12:25:25 -04:00
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
G_TYPE_BOOLEAN);
|
2021-11-29 14:44:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_color_profile_init (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
static void
|
|
|
|
on_cd_profile_connected (GObject *source_object,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
CdProfile *cd_profile = CD_PROFILE (source_object);
|
|
|
|
MetaColorProfile *color_profile = user_data;
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
if (!cd_profile_connect_finish (cd_profile, res, &error))
|
|
|
|
{
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_warning ("Failed to connect to colord profile %s: %s",
|
|
|
|
color_profile->cd_profile_id,
|
|
|
|
error->message);
|
|
|
|
|
2022-09-13 12:25:25 -04:00
|
|
|
color_profile->is_ready = TRUE;
|
|
|
|
g_signal_emit (color_profile, signals[READY], 0, FALSE);
|
|
|
|
return;
|
2021-11-30 05:56:31 -05:00
|
|
|
}
|
|
|
|
|
2022-09-13 12:25:25 -04:00
|
|
|
g_warn_if_fail (g_strcmp0 (cd_profile_get_id (cd_profile),
|
|
|
|
color_profile->cd_profile_id) == 0);
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_COLOR, "Color profile '%s' connected",
|
|
|
|
color_profile->cd_profile_id);
|
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
color_profile->is_ready = TRUE;
|
2022-09-13 12:25:25 -04:00
|
|
|
g_signal_emit (color_profile, signals[READY], 0, TRUE);
|
2021-11-30 05:56:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_cd_profile_created (GObject *source_object,
|
|
|
|
GAsyncResult *res,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
CdClient *cd_client = CD_CLIENT (source_object);
|
|
|
|
MetaColorProfile *color_profile = META_COLOR_PROFILE (user_data);
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
CdProfile *cd_profile;
|
|
|
|
|
|
|
|
cd_profile = cd_client_create_profile_finish (cd_client, res, &error);
|
|
|
|
if (!cd_profile)
|
|
|
|
{
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
return;
|
|
|
|
|
2022-09-13 12:25:25 -04:00
|
|
|
if (g_error_matches (error,
|
|
|
|
CD_CLIENT_ERROR, CD_CLIENT_ERROR_ALREADY_EXISTS))
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COLOR, "Tried to create duplicate profile %s",
|
|
|
|
color_profile->cd_profile_id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_warning ("Failed to create colord color profile %s: %s",
|
|
|
|
color_profile->cd_profile_id,
|
|
|
|
error->message);
|
|
|
|
}
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
color_profile->is_ready = TRUE;
|
2022-09-13 12:25:25 -04:00
|
|
|
g_signal_emit (color_profile, signals[READY], 0, FALSE);
|
2021-11-30 05:56:31 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_COLOR, "Created colord color profile '%s'",
|
|
|
|
color_profile->cd_profile_id);
|
|
|
|
|
|
|
|
color_profile->cd_profile = cd_profile;
|
|
|
|
|
|
|
|
cd_profile_connect (cd_profile, color_profile->cancellable,
|
|
|
|
on_cd_profile_connected, color_profile);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
create_cd_profile (MetaColorProfile *color_profile,
|
|
|
|
const char *checksum)
|
|
|
|
{
|
|
|
|
MetaColorManager *color_manager = color_profile->color_manager;
|
|
|
|
CdClient *cd_client = meta_color_manager_get_cd_client (color_manager);
|
|
|
|
const char *filename;
|
|
|
|
g_autoptr (GHashTable) profile_props = NULL;
|
|
|
|
|
|
|
|
filename = cd_icc_get_metadata_item (color_profile->cd_icc,
|
|
|
|
CD_PROFILE_PROPERTY_FILENAME);
|
|
|
|
|
|
|
|
profile_props = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
NULL, NULL);
|
|
|
|
g_hash_table_insert (profile_props,
|
|
|
|
(gpointer) CD_PROFILE_PROPERTY_FILENAME,
|
|
|
|
(gpointer) filename);
|
|
|
|
g_hash_table_insert (profile_props,
|
|
|
|
(gpointer) CD_PROFILE_METADATA_FILE_CHECKSUM,
|
|
|
|
(gpointer) checksum);
|
|
|
|
cd_client_create_profile (cd_client,
|
|
|
|
color_profile->cd_profile_id,
|
|
|
|
CD_OBJECT_SCOPE_TEMP,
|
|
|
|
profile_props,
|
|
|
|
color_profile->cancellable,
|
|
|
|
on_cd_profile_created,
|
|
|
|
color_profile);
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:44:56 -05:00
|
|
|
MetaColorProfile *
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
|
|
|
CdIcc *cd_icc,
|
|
|
|
GBytes *raw_bytes,
|
|
|
|
MetaColorCalibration *color_calibration)
|
2021-11-29 14:44:56 -05:00
|
|
|
{
|
|
|
|
MetaColorProfile *color_profile;
|
2021-11-30 05:56:31 -05:00
|
|
|
const char *checksum;
|
|
|
|
|
|
|
|
checksum = cd_icc_get_metadata_item (cd_icc,
|
|
|
|
CD_PROFILE_METADATA_FILE_CHECKSUM);
|
2021-11-29 14:44:56 -05:00
|
|
|
|
|
|
|
color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL);
|
|
|
|
color_profile->color_manager = color_manager;
|
|
|
|
color_profile->cd_icc = cd_icc;
|
|
|
|
color_profile->bytes = raw_bytes;
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
color_profile->calibration = color_calibration;
|
2021-11-30 05:56:31 -05:00
|
|
|
color_profile->cancellable = g_cancellable_new ();
|
2021-12-01 12:57:52 -05:00
|
|
|
color_profile->is_owner = TRUE;
|
2021-11-30 05:56:31 -05:00
|
|
|
|
|
|
|
color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum);
|
|
|
|
|
|
|
|
create_cd_profile (color_profile, checksum);
|
2021-11-29 14:44:56 -05:00
|
|
|
|
|
|
|
return color_profile;
|
|
|
|
}
|
|
|
|
|
2021-12-01 12:57:52 -05:00
|
|
|
static gboolean
|
|
|
|
notify_ready_idle (gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaColorProfile *color_profile = user_data;
|
|
|
|
|
|
|
|
color_profile->notify_ready_id = 0;
|
|
|
|
color_profile->is_ready = TRUE;
|
2022-09-13 12:25:25 -04:00
|
|
|
g_signal_emit (color_profile, signals[READY], 0, TRUE);
|
2021-12-01 12:57:52 -05:00
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaColorProfile *
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
|
|
|
CdProfile *cd_profile,
|
|
|
|
CdIcc *cd_icc,
|
|
|
|
GBytes *raw_bytes,
|
|
|
|
MetaColorCalibration *color_calibration)
|
2021-12-01 12:57:52 -05:00
|
|
|
{
|
|
|
|
MetaColorProfile *color_profile;
|
|
|
|
const char *checksum;
|
|
|
|
|
|
|
|
color_profile = g_object_new (META_TYPE_COLOR_PROFILE, NULL);
|
|
|
|
color_profile->color_manager = color_manager;
|
|
|
|
color_profile->cd_icc = cd_icc;
|
|
|
|
color_profile->bytes = raw_bytes;
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
color_profile->calibration = color_calibration;
|
2021-12-01 12:57:52 -05:00
|
|
|
color_profile->cancellable = g_cancellable_new ();
|
|
|
|
color_profile->is_owner = FALSE;
|
|
|
|
|
|
|
|
checksum = cd_icc_get_metadata_item (cd_icc,
|
|
|
|
CD_PROFILE_METADATA_FILE_CHECKSUM);
|
|
|
|
color_profile->cd_profile_id = g_strdup_printf ("icc-%s", checksum);
|
|
|
|
color_profile->cd_profile = g_object_ref (cd_profile);
|
|
|
|
|
|
|
|
color_profile->notify_ready_id = g_idle_add (notify_ready_idle,
|
|
|
|
color_profile);
|
|
|
|
|
|
|
|
return color_profile;
|
|
|
|
}
|
|
|
|
|
2021-11-29 14:44:56 -05:00
|
|
|
gboolean
|
|
|
|
meta_color_profile_equals_bytes (MetaColorProfile *color_profile,
|
|
|
|
GBytes *bytes)
|
|
|
|
{
|
|
|
|
return g_bytes_equal (color_profile->bytes, bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t *
|
|
|
|
meta_color_profile_get_data (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return g_bytes_get_data (color_profile->bytes, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
meta_color_profile_get_data_size (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return g_bytes_get_size (color_profile->bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
CdIcc *
|
|
|
|
meta_color_profile_get_cd_icc (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return color_profile->cd_icc;
|
|
|
|
}
|
2021-11-30 05:56:31 -05:00
|
|
|
|
2021-12-01 12:57:52 -05:00
|
|
|
CdProfile *
|
|
|
|
meta_color_profile_get_cd_profile (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return color_profile->cd_profile;
|
|
|
|
}
|
|
|
|
|
2021-11-30 05:56:31 -05:00
|
|
|
gboolean
|
|
|
|
meta_color_profile_is_ready (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return color_profile->is_ready;
|
|
|
|
}
|
2021-12-01 12:57:52 -05:00
|
|
|
|
|
|
|
const char *
|
|
|
|
meta_color_profile_get_id (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return color_profile->cd_profile_id;
|
|
|
|
}
|
2021-12-03 11:41:20 -05:00
|
|
|
|
2021-12-03 18:36:14 -05:00
|
|
|
const char *
|
|
|
|
meta_color_profile_get_file_path (MetaColorProfile *color_profile)
|
|
|
|
{
|
2022-09-13 12:11:15 -04:00
|
|
|
return cd_icc_get_metadata_item (color_profile->cd_icc,
|
|
|
|
CD_PROFILE_PROPERTY_FILENAME);
|
2021-12-03 18:36:14 -05:00
|
|
|
}
|
|
|
|
|
2021-12-03 11:41:20 -05:00
|
|
|
const char *
|
|
|
|
meta_color_profile_get_brightness_profile (MetaColorProfile *color_profile)
|
|
|
|
{
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
return color_profile->calibration->brightness_profile;
|
2021-12-03 11:41:20 -05:00
|
|
|
}
|
2021-12-03 18:37:20 -05:00
|
|
|
|
|
|
|
static void
|
|
|
|
set_blackbody_color_for_temperature (CdColorRGB *blackbody_color,
|
|
|
|
unsigned int temperature)
|
|
|
|
{
|
|
|
|
if (!cd_color_get_blackbody_rgb_full (temperature,
|
|
|
|
blackbody_color,
|
|
|
|
CD_COLOR_BLACKBODY_FLAG_USE_PLANCKIAN))
|
|
|
|
{
|
|
|
|
g_warning ("Failed to get blackbody for %uK", temperature);
|
|
|
|
cd_color_rgb_set (blackbody_color, 1.0, 1.0, 1.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_topic (META_DEBUG_COLOR,
|
|
|
|
"Using blackbody color from %uK: %.1f, %.1f, %.1f",
|
|
|
|
temperature,
|
|
|
|
blackbody_color->R,
|
|
|
|
blackbody_color->G,
|
|
|
|
blackbody_color->B);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaGammaLut *
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
generate_gamma_lut_from_vcgt (MetaColorProfile *color_profile,
|
|
|
|
cmsToneCurve **vcgt,
|
|
|
|
unsigned int temperature,
|
|
|
|
size_t lut_size)
|
2021-12-03 18:37:20 -05:00
|
|
|
{
|
|
|
|
CdColorRGB blackbody_color;
|
|
|
|
MetaGammaLut *lut;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_COLOR,
|
|
|
|
"Generating %zu sized GAMMA LUT using temperature %uK and VCGT",
|
|
|
|
lut_size, temperature);
|
|
|
|
|
|
|
|
set_blackbody_color_for_temperature (&blackbody_color, temperature);
|
|
|
|
|
|
|
|
lut = g_new0 (MetaGammaLut, 1);
|
|
|
|
lut->size = lut_size;
|
|
|
|
lut->red = g_new0 (uint16_t, lut_size);
|
|
|
|
lut->green = g_new0 (uint16_t, lut_size);
|
|
|
|
lut->blue = g_new0 (uint16_t, lut_size);
|
|
|
|
|
|
|
|
for (i = 0; i < lut_size; i++)
|
|
|
|
{
|
|
|
|
cmsFloat32Number in;
|
|
|
|
|
|
|
|
in = (double) i / (double) (lut_size - 1);
|
|
|
|
lut->red[i] =
|
|
|
|
cmsEvalToneCurveFloat (vcgt[0], in) *
|
|
|
|
blackbody_color.R * (double) 0xffff;
|
|
|
|
lut->green[i] =
|
|
|
|
cmsEvalToneCurveFloat (vcgt[1], in) *
|
|
|
|
blackbody_color.G * (double) 0xffff;
|
|
|
|
lut->blue[i] =
|
|
|
|
cmsEvalToneCurveFloat (vcgt[2], in) *
|
|
|
|
blackbody_color.B * (gdouble) 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
return lut;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaGammaLut *
|
|
|
|
generate_gamma_lut (MetaColorProfile *color_profile,
|
|
|
|
unsigned int temperature,
|
|
|
|
size_t lut_size)
|
|
|
|
{
|
|
|
|
CdColorRGB blackbody_color;
|
|
|
|
MetaGammaLut *lut;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_COLOR,
|
|
|
|
"Generating %zu sized GAMMA LUT using temperature %uK",
|
|
|
|
lut_size, temperature);
|
|
|
|
|
|
|
|
set_blackbody_color_for_temperature (&blackbody_color, temperature);
|
|
|
|
|
|
|
|
lut = g_new0 (MetaGammaLut, 1);
|
|
|
|
lut->size = lut_size;
|
|
|
|
lut->red = g_new0 (uint16_t, lut_size);
|
|
|
|
lut->green = g_new0 (uint16_t, lut_size);
|
|
|
|
lut->blue = g_new0 (uint16_t, lut_size);
|
|
|
|
|
|
|
|
for (i = 0; i < lut_size; i++)
|
|
|
|
{
|
|
|
|
uint16_t in;
|
|
|
|
|
|
|
|
in = (i * 0xffff) / (lut->size - 1);
|
|
|
|
lut->red[i] = in * blackbody_color.R;
|
|
|
|
lut->green[i] = in * blackbody_color.G;
|
|
|
|
lut->blue[i] = in * blackbody_color.B;
|
|
|
|
}
|
|
|
|
|
|
|
|
return lut;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaGammaLut *
|
|
|
|
meta_color_profile_generate_gamma_lut (MetaColorProfile *color_profile,
|
|
|
|
unsigned int temperature,
|
|
|
|
size_t lut_size)
|
|
|
|
{
|
2022-09-03 09:01:40 -04:00
|
|
|
g_assert (lut_size > 0);
|
2021-12-03 18:37:20 -05:00
|
|
|
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
if (color_profile->calibration->has_vcgt)
|
2021-12-03 18:37:20 -05:00
|
|
|
{
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
return generate_gamma_lut_from_vcgt (color_profile,
|
|
|
|
color_profile->calibration->vcgt,
|
2021-12-03 18:37:20 -05:00
|
|
|
temperature, lut_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return generate_gamma_lut (color_profile, temperature, lut_size);
|
|
|
|
}
|
|
|
|
}
|
color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile",
which is necessary to properly support color transform
calibration profiles from an EFI variable.
These types of profiles are intended to be applied using the color
transformation matrix (CTM) property on the output, which makes the
presented output match sRGB. In order to avoid color profile aware
clients making the wrong assumption, we must set the profile exposed
externally to be what is the expected perceived result, i.e. sRGB, while
still applying CTM from the real ICC profile.
The separation is done by introducing a MetaColorCalibration struct,
that is filled with relevant data. For profiles coming from EFI, a
created profile is practically an sRGB one, but the calibration data
comes from EFI, while for other profiles, the calibration data and the
ICC profile itself come from the same source.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
2022-08-30 17:30:35 -04:00
|
|
|
|
|
|
|
const MetaColorCalibration *
|
|
|
|
meta_color_profile_get_calibration (MetaColorProfile *color_profile)
|
|
|
|
{
|
|
|
|
return color_profile->calibration;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaColorCalibration *
|
|
|
|
meta_color_calibration_new (CdIcc *cd_icc,
|
|
|
|
const CdMat3x3 *adaptation_matrix)
|
|
|
|
{
|
|
|
|
MetaColorCalibration *color_calibration;
|
|
|
|
cmsHPROFILE lcms_profile;
|
|
|
|
const cmsToneCurve **vcgt;
|
|
|
|
const char *brightness_profile;
|
|
|
|
|
|
|
|
color_calibration = g_new0 (MetaColorCalibration, 1);
|
|
|
|
|
|
|
|
lcms_profile = cd_icc_get_handle (cd_icc);
|
|
|
|
vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag);
|
|
|
|
if (vcgt && vcgt[0])
|
|
|
|
{
|
|
|
|
color_calibration->has_vcgt = TRUE;
|
|
|
|
color_calibration->vcgt[0] = cmsDupToneCurve (vcgt[0]);
|
|
|
|
color_calibration->vcgt[1] = cmsDupToneCurve (vcgt[1]);
|
|
|
|
color_calibration->vcgt[2] = cmsDupToneCurve (vcgt[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
brightness_profile =
|
|
|
|
cd_icc_get_metadata_item (cd_icc, CD_PROFILE_METADATA_SCREEN_BRIGHTNESS);
|
|
|
|
if (brightness_profile)
|
|
|
|
color_calibration->brightness_profile = g_strdup (brightness_profile);
|
|
|
|
|
|
|
|
if (adaptation_matrix)
|
|
|
|
{
|
|
|
|
color_calibration->has_adaptation_matrix = TRUE;
|
|
|
|
color_calibration->adaptation_matrix = *adaptation_matrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
return color_calibration;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_color_calibration_free (MetaColorCalibration *color_calibration)
|
|
|
|
{
|
|
|
|
cmsFreeToneCurveTriple (color_calibration->vcgt);
|
|
|
|
g_free (color_calibration->brightness_profile);
|
|
|
|
g_free (color_calibration);
|
|
|
|
}
|