| Index: ash/display/display_color_manager_chromeos.cc
|
| diff --git a/ash/display/display_color_manager_chromeos.cc b/ash/display/display_color_manager_chromeos.cc
|
| index 1241978958018acff967d30fbfd9dcb2d0c961dd..0bb29958d281382f75262d9cd67d7bf856a5ea36 100644
|
| --- a/ash/display/display_color_manager_chromeos.cc
|
| +++ b/ash/display/display_color_manager_chromeos.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "ash/display/display_color_manager_chromeos.h"
|
|
|
| +#include <stdint.h>
|
| +
|
| #include <utility>
|
|
|
| #include "base/bind.h"
|
| @@ -31,10 +33,26 @@ namespace ash {
|
|
|
| namespace {
|
|
|
| -bool ParseFile(const base::FilePath& path,
|
| +base::FilePath PathForProductID(int64_t product_id) {
|
| + base::FilePath path;
|
| + CHECK(
|
| + PathService::Get(chromeos::DIR_DEVICE_COLOR_CALIBRATION_PROFILES, &path));
|
| + path = path.Append(base::StringPrintf("%08" PRIx64 ".icc", product_id));
|
| + return path;
|
| +}
|
| +
|
| +bool ParseFile(bool has_color_correction_matrix,
|
| + int64_t product_id,
|
| DisplayColorManager::ColorCalibrationData* data) {
|
| + base::FilePath path = PathForProductID(product_id);
|
| + VLOG(1) << "Trying ICC file " << path.value()
|
| + << " with product id: " << product_id
|
| + << " has_color_correction_matrix: "
|
| + << (has_color_correction_matrix ? "true" : "false");
|
| +
|
| if (!base::PathExists(path)) // No icc file for this display; not an error.
|
| return false;
|
| +
|
| qcms_profile* display_profile = qcms_profile_from_path(path.value().c_str());
|
|
|
| if (!display_profile) {
|
| @@ -44,39 +62,113 @@ bool ParseFile(const base::FilePath& path,
|
|
|
| size_t vcgt_channel_length =
|
| qcms_profile_get_vcgt_channel_length(display_profile);
|
| - if (!vcgt_channel_length) {
|
| +
|
| + if (!has_color_correction_matrix && !vcgt_channel_length) {
|
| LOG(WARNING) << "No vcgt table in ICC file: " << path.value();
|
| qcms_profile_release(display_profile);
|
| return false;
|
| }
|
|
|
| - std::vector<uint16_t> vcgt_data;
|
| - vcgt_data.resize(vcgt_channel_length * 3);
|
| - if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) {
|
| - LOG(WARNING) << "Unable to get vcgt data";
|
| - qcms_profile_release(display_profile);
|
| - return false;
|
| - }
|
| + if (vcgt_channel_length) {
|
| + if (has_color_correction_matrix) {
|
| + VLOG(1) << "Using VCGT data on CTM enabled platform.";
|
| + }
|
| +
|
| + std::vector<uint16_t> vcgt_data;
|
| + vcgt_data.resize(vcgt_channel_length * 3);
|
| + if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) {
|
| + LOG(WARNING) << "Unable to get vcgt data";
|
| + qcms_profile_release(display_profile);
|
| + return false;
|
| + }
|
| +
|
| + data->gamma_lut.resize(vcgt_channel_length);
|
| + for (size_t i = 0; i < vcgt_channel_length; ++i) {
|
| + data->gamma_lut[i].r = vcgt_data[i];
|
| + data->gamma_lut[i].g = vcgt_data[vcgt_channel_length + i];
|
| + data->gamma_lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
|
| + }
|
| + } else {
|
| + VLOG(1) << "Using full degamma/gamma/CTM from profile.";
|
| + qcms_profile* srgb_profile = qcms_profile_sRGB();
|
| +
|
| + qcms_transform* transform =
|
| + qcms_transform_create(srgb_profile, QCMS_DATA_RGB_8, display_profile,
|
| + QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
|
| +
|
| + if (!transform) {
|
| + LOG(WARNING)
|
| + << "Unable to create transformation from sRGB to display profile.";
|
| +
|
| + qcms_profile_release(display_profile);
|
| + qcms_profile_release(srgb_profile);
|
| + return false;
|
| + }
|
|
|
| - data->lut.resize(vcgt_channel_length);
|
| - for (size_t i = 0; i < vcgt_channel_length; ++i) {
|
| - data->lut[i].r = vcgt_data[i];
|
| - data->lut[i].g = vcgt_data[vcgt_channel_length + i];
|
| - data->lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
|
| + if (!qcms_transform_is_matrix(transform)) {
|
| + LOG(WARNING) << "No transformation matrix available";
|
| +
|
| + qcms_transform_release(transform);
|
| + qcms_profile_release(display_profile);
|
| + qcms_profile_release(srgb_profile);
|
| + return false;
|
| + }
|
| +
|
| + size_t degamma_size = qcms_transform_get_input_trc_rgba(
|
| + transform, srgb_profile, QCMS_TRC_USHORT, NULL);
|
| + size_t gamma_size = qcms_transform_get_output_trc_rgba(
|
| + transform, display_profile, QCMS_TRC_USHORT, NULL);
|
| +
|
| + if (degamma_size == 0 || gamma_size == 0) {
|
| + LOG(WARNING)
|
| + << "Invalid number of elements in gamma tables: degamma size = "
|
| + << degamma_size << " gamma size = " << gamma_size;
|
| +
|
| + qcms_transform_release(transform);
|
| + qcms_profile_release(display_profile);
|
| + qcms_profile_release(srgb_profile);
|
| + return false;
|
| + }
|
| +
|
| + std::vector<uint16_t> degamma_data;
|
| + std::vector<uint16_t> gamma_data;
|
| + degamma_data.resize(degamma_size * 4);
|
| + gamma_data.resize(gamma_size * 4);
|
| +
|
| + qcms_transform_get_input_trc_rgba(transform, srgb_profile, QCMS_TRC_USHORT,
|
| + °amma_data[0]);
|
| + qcms_transform_get_output_trc_rgba(transform, display_profile,
|
| + QCMS_TRC_USHORT, &gamma_data[0]);
|
| +
|
| + data->degamma_lut.resize(degamma_size);
|
| + for (size_t i = 0; i < degamma_size; ++i) {
|
| + data->degamma_lut[i].r = degamma_data[i * 4];
|
| + data->degamma_lut[i].g = degamma_data[(i * 4) + 1];
|
| + data->degamma_lut[i].b = degamma_data[(i * 4) + 2];
|
| + }
|
| +
|
| + data->gamma_lut.resize(gamma_size);
|
| + for (size_t i = 0; i < gamma_size; ++i) {
|
| + data->gamma_lut[i].r = gamma_data[i * 4];
|
| + data->gamma_lut[i].g = gamma_data[(i * 4) + 1];
|
| + data->gamma_lut[i].b = gamma_data[(i * 4) + 2];
|
| + }
|
| +
|
| + data->correction_matrix.resize(9);
|
| + for (int i = 0; i < 9; ++i) {
|
| + data->correction_matrix[i] =
|
| + qcms_transform_get_matrix(transform, i / 3, i % 3);
|
| + }
|
| +
|
| + qcms_transform_release(transform);
|
| + qcms_profile_release(srgb_profile);
|
| }
|
| +
|
| + VLOG(1) << "ICC file successfully parsed";
|
| qcms_profile_release(display_profile);
|
| return true;
|
| }
|
|
|
| -base::FilePath PathForDisplaySnapshot(const ui::DisplaySnapshot* snapshot) {
|
| - base::FilePath path;
|
| - CHECK(
|
| - PathService::Get(chromeos::DIR_DEVICE_COLOR_CALIBRATION_PROFILES, &path));
|
| - path = path.Append(
|
| - base::StringPrintf("%08" PRIx64 ".icc", snapshot->product_id()));
|
| - return path;
|
| -}
|
| -
|
| } // namespace
|
|
|
| DisplayColorManager::DisplayColorManager(
|
| @@ -106,9 +198,11 @@ void DisplayColorManager::OnDisplayModeChanged(
|
| void DisplayColorManager::ApplyDisplayColorCalibration(int64_t display_id,
|
| int64_t product_id) {
|
| if (calibration_map_.find(product_id) != calibration_map_.end()) {
|
| - ColorCalibrationData* ramp = calibration_map_[product_id];
|
| - if (!configurator_->SetGammaRamp(display_id, ramp->lut))
|
| - LOG(WARNING) << "Error applying gamma ramp";
|
| + ColorCalibrationData* data = calibration_map_[product_id];
|
| + if (!configurator_->SetColorCorrection(display_id, data->degamma_lut,
|
| + data->gamma_lut,
|
| + data->correction_matrix))
|
| + LOG(WARNING) << "Error applying color correction data";
|
| }
|
| }
|
|
|
| @@ -119,14 +213,11 @@ void DisplayColorManager::LoadCalibrationForDisplay(
|
| return;
|
| }
|
|
|
| - base::FilePath path = PathForDisplaySnapshot(display);
|
| - VLOG(1) << "Loading ICC file " << path.value()
|
| - << " for display id: " << display->display_id()
|
| - << " with product id: " << display->product_id();
|
| -
|
| scoped_ptr<ColorCalibrationData> data(new ColorCalibrationData());
|
| - base::Callback<bool(void)> request(
|
| - base::Bind(&ParseFile, path, base::Unretained(data.get())));
|
| + base::Callback<bool(void)> request;
|
| + request = base::Bind(&ParseFile, display->has_color_correction_matrix(),
|
| + display->product_id(), base::Unretained(data.get()));
|
| +
|
| base::PostTaskAndReplyWithResult(
|
| blocking_pool_, FROM_HERE, request,
|
| base::Bind(&DisplayColorManager::UpdateCalibrationData, AsWeakPtr(),
|
|
|