Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: ash/display/display_color_manager_chromeos.cc

Issue 1182063002: Add support for more advanced color correction (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@qcms-fixed-point-gamma
Patch Set: Refactor for glevin@ and load VCGT always Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/display/display_color_manager_chromeos.h" 5 #include "ash/display/display_color_manager_chromeos.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
(...skipping 11 matching lines...) Expand all
22 #include "ui/display/types/display_snapshot.h" 22 #include "ui/display/types/display_snapshot.h"
23 #include "ui/display/types/gamma_ramp_rgb_entry.h" 23 #include "ui/display/types/gamma_ramp_rgb_entry.h"
24 #include "ui/display/types/native_display_delegate.h" 24 #include "ui/display/types/native_display_delegate.h"
25 #include "ui/gfx/display.h" 25 #include "ui/gfx/display.h"
26 #include "ui/gfx/screen.h" 26 #include "ui/gfx/screen.h"
27 27
28 namespace ash { 28 namespace ash {
29 29
30 namespace { 30 namespace {
31 31
32 bool ParseFile(const base::FilePath& path, 32 base::FilePath PathForProductID(int64_t product_id) {
33 base::FilePath path;
34 CHECK(
35 PathService::Get(chromeos::DIR_DEVICE_COLOR_CALIBRATION_PROFILES, &path));
36 path = path.Append(base::StringPrintf("%08" PRIx64 ".icc", product_id));
37 return path;
38 }
39
40 bool ParseFile(bool has_color_correction_matrix,
41 int64_t product_id,
33 DisplayColorManager::ColorCalibrationData* data) { 42 DisplayColorManager::ColorCalibrationData* data) {
43 base::FilePath path = PathForProductID(product_id);
44 VLOG(1) << "Trying ICC file " << path.value()
45 << " with product id: " << product_id
46 << " has_color_correction_matrix: "
47 << (has_color_correction_matrix ? "true" : "false");
48
34 if (!base::PathExists(path)) // No icc file for this display; not an error. 49 if (!base::PathExists(path)) // No icc file for this display; not an error.
35 return false; 50 return false;
51
36 qcms_profile* display_profile = qcms_profile_from_path(path.value().c_str()); 52 qcms_profile* display_profile = qcms_profile_from_path(path.value().c_str());
37 53
38 if (!display_profile) { 54 if (!display_profile) {
39 LOG(WARNING) << "Unable to load ICC file: " << path.value(); 55 LOG(WARNING) << "Unable to load ICC file: " << path.value();
40 return false; 56 return false;
41 } 57 }
42 58
43 size_t vcgt_channel_length = 59 size_t vcgt_channel_length =
44 qcms_profile_get_vcgt_channel_length(display_profile); 60 qcms_profile_get_vcgt_channel_length(display_profile);
45 if (!vcgt_channel_length) { 61
62 if (!has_color_correction_matrix && !vcgt_channel_length) {
46 LOG(WARNING) << "No vcgt table in ICC file: " << path.value(); 63 LOG(WARNING) << "No vcgt table in ICC file: " << path.value();
47 qcms_profile_release(display_profile); 64 qcms_profile_release(display_profile);
48 return false; 65 return false;
49 } 66 }
50 67
51 std::vector<uint16_t> vcgt_data; 68 if (vcgt_channel_length) {
52 vcgt_data.resize(vcgt_channel_length * 3); 69 if (has_color_correction_matrix) {
53 if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) { 70 VLOG(1) << "Using VCGT data on CTM enabled platform.";
54 LOG(WARNING) << "Unable to get vcgt data"; 71 }
55 qcms_profile_release(display_profile); 72
56 return false; 73 std::vector<uint16_t> vcgt_data;
74 vcgt_data.resize(vcgt_channel_length * 3);
75 if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) {
76 LOG(WARNING) << "Unable to get vcgt data";
77 qcms_profile_release(display_profile);
78 return false;
79 }
80
81 data->gamma_lut.resize(vcgt_channel_length);
82 for (size_t i = 0; i < vcgt_channel_length; ++i) {
83 data->gamma_lut[i].r = vcgt_data[i];
84 data->gamma_lut[i].g = vcgt_data[vcgt_channel_length + i];
85 data->gamma_lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
86 }
87 } else {
88 VLOG(1) << "Using full degamma/gamma/CTM from profile.";
89 qcms_profile* srgb_profile = qcms_profile_sRGB();
90
91 qcms_transform* transform =
92 qcms_transform_create(srgb_profile, QCMS_DATA_RGB_8, display_profile,
93 QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
94
95 if (!transform) {
96 LOG(WARNING)
97 << "Unable to create transformation from sRGB to display profile.";
98
99 qcms_profile_release(display_profile);
100 qcms_profile_release(srgb_profile);
101 return false;
102 }
103
104 if (!qcms_transform_is_matrix(transform)) {
105 LOG(WARNING) << "No transformation matrix available";
106
107 qcms_transform_release(transform);
108 qcms_profile_release(display_profile);
109 qcms_profile_release(srgb_profile);
110 return false;
111 }
112
113 size_t degamma_size = qcms_transform_get_input_trc_rgba(
114 transform, srgb_profile, QCMS_TRC_FLOAT, NULL);
115 size_t gamma_size = qcms_transform_get_output_trc_rgba(
116 transform, display_profile, QCMS_TRC_FLOAT, NULL);
117
118 if (degamma_size == 0 || gamma_size == 0) {
119 LOG(WARNING)
120 << "Invalid number of elements in gamma tables: degamma size = "
121 << degamma_size << " gamma size = " << gamma_size;
122
123 qcms_transform_release(transform);
124 qcms_profile_release(display_profile);
125 qcms_profile_release(srgb_profile);
126 return false;
127 }
128
129 std::vector<float> degamma_data;
130 std::vector<float> gamma_data;
131 degamma_data.resize(degamma_size * 4);
132 gamma_data.resize(gamma_size * 4);
133
134 qcms_transform_get_input_trc_rgba(transform, srgb_profile, QCMS_TRC_FLOAT,
135 &degamma_data[0]);
136 qcms_transform_get_output_trc_rgba(transform, display_profile,
137 QCMS_TRC_FLOAT, &gamma_data[0]);
138
139 #define FLOAT_TO_FIXED(f) static_cast<uint32_t>(f * ((1 << 24)));
140 data->degamma_lut.resize(degamma_size);
141 for (size_t i = 0; i < degamma_size; ++i) {
142 data->degamma_lut[i].r = FLOAT_TO_FIXED(degamma_data[i * 4]);
143 data->degamma_lut[i].g = FLOAT_TO_FIXED(degamma_data[(i * 4) + 1]);
144 data->degamma_lut[i].b = FLOAT_TO_FIXED(degamma_data[(i * 4) + 2]);
145 }
146
147 data->gamma_lut.resize(gamma_size);
148 for (size_t i = 0; i < gamma_size; ++i) {
149 data->gamma_lut[i].r = FLOAT_TO_FIXED(gamma_data[i * 4]);
150 data->gamma_lut[i].g = FLOAT_TO_FIXED(gamma_data[(i * 4) + 1]);
151 data->gamma_lut[i].b = FLOAT_TO_FIXED(gamma_data[(i * 4) + 2]);
152 }
153 #undef FLOAT_TO_FIXED
154
155 for (int i = 0; i < 9; ++i) {
156 data->correction_matrix[i] =
157 qcms_transform_get_matrix(transform, i / 3, i % 3);
158 }
159
160 qcms_transform_release(transform);
161 qcms_profile_release(srgb_profile);
57 } 162 }
58 163
59 data->lut.resize(vcgt_channel_length); 164 VLOG(1) << "ICC file successfully parsed";
60 for (size_t i = 0; i < vcgt_channel_length; ++i) {
61 data->lut[i].r = vcgt_data[i];
62 data->lut[i].g = vcgt_data[vcgt_channel_length + i];
63 data->lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
64 }
65 qcms_profile_release(display_profile); 165 qcms_profile_release(display_profile);
66 return true; 166 return true;
67 } 167 }
68 168
69 base::FilePath PathForDisplaySnapshot(const ui::DisplaySnapshot* snapshot) {
70 base::FilePath path;
71 CHECK(
72 PathService::Get(chromeos::DIR_DEVICE_COLOR_CALIBRATION_PROFILES, &path));
73 path = path.Append(
74 base::StringPrintf("%08" PRIx64 ".icc", snapshot->product_id()));
75 return path;
76 }
77
78 } // namespace 169 } // namespace
79 170
80 DisplayColorManager::DisplayColorManager( 171 DisplayColorManager::DisplayColorManager(
81 ui::DisplayConfigurator* configurator, 172 ui::DisplayConfigurator* configurator,
82 base::SequencedWorkerPool* blocking_pool) 173 base::SequencedWorkerPool* blocking_pool)
83 : configurator_(configurator), blocking_pool_(blocking_pool) { 174 : configurator_(configurator), blocking_pool_(blocking_pool) {
84 configurator_->AddObserver(this); 175 configurator_->AddObserver(this);
85 } 176 }
86 177
87 DisplayColorManager::~DisplayColorManager() { 178 DisplayColorManager::~DisplayColorManager() {
88 configurator_->RemoveObserver(this); 179 configurator_->RemoveObserver(this);
89 STLDeleteValues(&calibration_map_); 180 STLDeleteValues(&calibration_map_);
90 } 181 }
91 182
92 void DisplayColorManager::OnDisplayModeChanged( 183 void DisplayColorManager::OnDisplayModeChanged(
93 const ui::DisplayConfigurator::DisplayStateList& display_states) { 184 const ui::DisplayConfigurator::DisplayStateList& display_states) {
94 for (const ui::DisplaySnapshot* state : display_states) { 185 for (const ui::DisplaySnapshot* state : display_states) {
95 if (calibration_map_[state->product_id()]) { 186 if (calibration_map_[state->product_id()]) {
96 ApplyDisplayColorCalibration(state->display_id(), state->product_id()); 187 ApplyDisplayColorCalibration(state->display_id(), state->product_id());
97 } else { 188 } else {
98 if (state->product_id() != ui::DisplaySnapshot::kInvalidProductID) 189 if (state->product_id() != ui::DisplaySnapshot::kInvalidProductID)
99 LoadCalibrationForDisplay(state); 190 LoadCalibrationForDisplay(state);
100 } 191 }
101 } 192 }
102 } 193 }
103 194
104 void DisplayColorManager::ApplyDisplayColorCalibration(int64_t display_id, 195 void DisplayColorManager::ApplyDisplayColorCalibration(int64_t display_id,
105 int64_t product_id) { 196 int64_t product_id) {
106 if (calibration_map_.find(product_id) != calibration_map_.end()) { 197 if (calibration_map_.find(product_id) != calibration_map_.end()) {
107 ColorCalibrationData* ramp = calibration_map_[product_id]; 198 ColorCalibrationData* data = calibration_map_[product_id];
108 if (!configurator_->SetGammaRamp(display_id, ramp->lut)) 199 if (data->degamma_lut.size() == 0) {
109 LOG(WARNING) << "Error applying gamma ramp"; 200 if (!configurator_->SetGammaRamp(display_id, data->gamma_lut))
201 LOG(WARNING) << "Error applying gamma ramp";
202 } else {
203 if (!configurator_->SetColorCorrection(display_id, data->degamma_lut,
204 data->gamma_lut,
205 data->correction_matrix))
206 LOG(WARNING) << "Error applying color correction data";
207 }
110 } 208 }
111 } 209 }
112 210
113 void DisplayColorManager::LoadCalibrationForDisplay( 211 void DisplayColorManager::LoadCalibrationForDisplay(
114 const ui::DisplaySnapshot* display) { 212 const ui::DisplaySnapshot* display) {
115 if (display->display_id() == gfx::Display::kInvalidDisplayID) { 213 if (display->display_id() == gfx::Display::kInvalidDisplayID) {
116 LOG(WARNING) << "Trying to load calibration data for invalid display id"; 214 LOG(WARNING) << "Trying to load calibration data for invalid display id";
117 return; 215 return;
118 } 216 }
119 217
120 base::FilePath path = PathForDisplaySnapshot(display); 218 scoped_ptr<ColorCalibrationData> data(new ColorCalibrationData());
121 VLOG(1) << "Loading ICC file " << path.value() 219 base::Callback<bool(void)> request;
122 << " for display id: " << display->display_id() 220 request = base::Callback<bool(void)>(
123 << " with product id: " << display->product_id(); 221 base::Bind(&ParseFile, display->has_color_correction_matrix(),
222 display->product_id(), base::Unretained(data.get())));
124 223
125 scoped_ptr<ColorCalibrationData> data(new ColorCalibrationData());
126 base::Callback<bool(void)> request(
127 base::Bind(&ParseFile, path, base::Unretained(data.get())));
128 base::PostTaskAndReplyWithResult( 224 base::PostTaskAndReplyWithResult(
129 blocking_pool_, FROM_HERE, request, 225 blocking_pool_, FROM_HERE, request,
130 base::Bind(&DisplayColorManager::UpdateCalibrationData, AsWeakPtr(), 226 base::Bind(&DisplayColorManager::UpdateCalibrationData, AsWeakPtr(),
131 display->display_id(), display->product_id(), 227 display->display_id(), display->product_id(),
132 base::Passed(data.Pass()))); 228 base::Passed(data.Pass())));
133 } 229 }
134 230
135 void DisplayColorManager::UpdateCalibrationData( 231 void DisplayColorManager::UpdateCalibrationData(
136 int64_t display_id, 232 int64_t display_id,
137 int64_t product_id, 233 int64_t product_id,
138 scoped_ptr<ColorCalibrationData> data, 234 scoped_ptr<ColorCalibrationData> data,
139 bool success) { 235 bool success) {
140 DCHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_UI); 236 DCHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_UI);
141 if (success) { 237 if (success) {
142 // The map takes over ownership of the underlying memory. 238 // The map takes over ownership of the underlying memory.
143 calibration_map_[product_id] = data.release(); 239 calibration_map_[product_id] = data.release();
144 ApplyDisplayColorCalibration(display_id, product_id); 240 ApplyDisplayColorCalibration(display_id, product_id);
145 } 241 }
146 } 242 }
147 243
148 DisplayColorManager::ColorCalibrationData::ColorCalibrationData() {} 244 DisplayColorManager::ColorCalibrationData::ColorCalibrationData() {}
149 245
150 DisplayColorManager::ColorCalibrationData::~ColorCalibrationData() {} 246 DisplayColorManager::ColorCalibrationData::~ColorCalibrationData() {}
151 247
152 } // namespace ash 248 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698