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

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: Rebase after quirks changes Created 4 years, 8 months 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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/stl_util.h" 12 #include "base/stl_util.h"
13 #include "base/task_runner_util.h" 13 #include "base/task_runner_util.h"
14 #include "base/threading/sequenced_worker_pool.h" 14 #include "base/threading/sequenced_worker_pool.h"
15 #include "components/quirks/quirks_manager.h" 15 #include "components/quirks/quirks_manager.h"
16 #include "third_party/qcms/src/qcms.h" 16 #include "third_party/qcms/src/qcms.h"
17 #include "ui/display/types/display_snapshot.h" 17 #include "ui/display/types/display_snapshot.h"
18 #include "ui/display/types/gamma_ramp_rgb_entry.h" 18 #include "ui/display/types/gamma_ramp_rgb_entry.h"
19 #include "ui/gfx/display.h" 19 #include "ui/gfx/display.h"
20 20
21 namespace ash { 21 namespace ash {
22 22
23 namespace { 23 namespace {
24 24
25 scoped_ptr<DisplayColorManager::ColorCalibrationData> ParseDisplayProfile( 25 scoped_ptr<DisplayColorManager::ColorCalibrationData> ParseDisplayProfile(
26 const base::FilePath& path) { 26 const base::FilePath& path,
27 bool has_color_correction_matrix) {
28 VLOG(1) << "Trying ICC file " << path.value()
29 << " has_color_correction_matrix: "
30 << (has_color_correction_matrix ? "true" : "false");
27 qcms_profile* display_profile = qcms_profile_from_path(path.value().c_str()); 31 qcms_profile* display_profile = qcms_profile_from_path(path.value().c_str());
28 if (!display_profile) { 32 if (!display_profile) {
29 LOG(WARNING) << "Unable to load ICC file: " << path.value(); 33 LOG(WARNING) << "Unable to load ICC file: " << path.value();
30 return nullptr; 34 return nullptr;
31 } 35 }
32 36
33 size_t vcgt_channel_length = 37 size_t vcgt_channel_length =
34 qcms_profile_get_vcgt_channel_length(display_profile); 38 qcms_profile_get_vcgt_channel_length(display_profile);
35 if (!vcgt_channel_length) { 39
40 if (!has_color_correction_matrix && !vcgt_channel_length) {
36 LOG(WARNING) << "No vcgt table in ICC file: " << path.value(); 41 LOG(WARNING) << "No vcgt table in ICC file: " << path.value();
37 qcms_profile_release(display_profile); 42 qcms_profile_release(display_profile);
38 return nullptr; 43 return nullptr;
39 } 44 }
40 45
41 std::vector<uint16_t> vcgt_data;
42 vcgt_data.resize(vcgt_channel_length * 3);
43 if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) {
44 LOG(WARNING) << "Unable to get vcgt data";
45 qcms_profile_release(display_profile);
46 return nullptr;
47 }
48
49 scoped_ptr<DisplayColorManager::ColorCalibrationData> data( 46 scoped_ptr<DisplayColorManager::ColorCalibrationData> data(
50 new DisplayColorManager::ColorCalibrationData()); 47 new DisplayColorManager::ColorCalibrationData());
51 data->lut.resize(vcgt_channel_length); 48 if (vcgt_channel_length) {
52 for (size_t i = 0; i < vcgt_channel_length; ++i) { 49 VLOG_IF(1, has_color_correction_matrix)
53 data->lut[i].r = vcgt_data[i]; 50 << "Using VCGT data on CTM enabled platform.";
54 data->lut[i].g = vcgt_data[vcgt_channel_length + i]; 51
55 data->lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i]; 52 std::vector<uint16_t> vcgt_data;
53 vcgt_data.resize(vcgt_channel_length * 3);
54 if (!qcms_profile_get_vcgt_rgb_channels(display_profile, &vcgt_data[0])) {
55 LOG(WARNING) << "Unable to get vcgt data";
56 qcms_profile_release(display_profile);
57 return nullptr;
58 }
59
60 data->gamma_lut.resize(vcgt_channel_length);
61 for (size_t i = 0; i < vcgt_channel_length; ++i) {
62 data->gamma_lut[i].r = vcgt_data[i];
63 data->gamma_lut[i].g = vcgt_data[vcgt_channel_length + i];
64 data->gamma_lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
65 }
66 } else {
67 VLOG(1) << "Using full degamma/gamma/CTM from profile.";
68 qcms_profile* srgb_profile = qcms_profile_sRGB();
69
70 qcms_transform* transform =
71 qcms_transform_create(srgb_profile, QCMS_DATA_RGB_8, display_profile,
72 QCMS_DATA_RGB_8, QCMS_INTENT_PERCEPTUAL);
73
74 if (!transform) {
75 LOG(WARNING)
76 << "Unable to create transformation from sRGB to display profile.";
77
78 qcms_profile_release(display_profile);
79 qcms_profile_release(srgb_profile);
80 return nullptr;
81 }
82
83 if (!qcms_transform_is_matrix(transform)) {
84 LOG(WARNING) << "No transformation matrix available";
85
86 qcms_transform_release(transform);
87 qcms_profile_release(display_profile);
88 qcms_profile_release(srgb_profile);
89 return nullptr;
90 }
91
92 size_t degamma_size = qcms_transform_get_input_trc_rgba(
93 transform, srgb_profile, QCMS_TRC_USHORT, NULL);
94 size_t gamma_size = qcms_transform_get_output_trc_rgba(
95 transform, display_profile, QCMS_TRC_USHORT, NULL);
96
97 if (degamma_size == 0 || gamma_size == 0) {
98 LOG(WARNING)
99 << "Invalid number of elements in gamma tables: degamma size = "
100 << degamma_size << " gamma size = " << gamma_size;
101
102 qcms_transform_release(transform);
103 qcms_profile_release(display_profile);
104 qcms_profile_release(srgb_profile);
105 return nullptr;
106 }
107
108 std::vector<uint16_t> degamma_data;
109 std::vector<uint16_t> gamma_data;
110 degamma_data.resize(degamma_size * 4);
111 gamma_data.resize(gamma_size * 4);
112
113 qcms_transform_get_input_trc_rgba(transform, srgb_profile, QCMS_TRC_USHORT,
114 &degamma_data[0]);
115 qcms_transform_get_output_trc_rgba(transform, display_profile,
116 QCMS_TRC_USHORT, &gamma_data[0]);
117
118 data->degamma_lut.resize(degamma_size);
119 for (size_t i = 0; i < degamma_size; ++i) {
120 data->degamma_lut[i].r = degamma_data[i * 4];
121 data->degamma_lut[i].g = degamma_data[(i * 4) + 1];
122 data->degamma_lut[i].b = degamma_data[(i * 4) + 2];
123 }
124
125 data->gamma_lut.resize(gamma_size);
126 for (size_t i = 0; i < gamma_size; ++i) {
127 data->gamma_lut[i].r = gamma_data[i * 4];
128 data->gamma_lut[i].g = gamma_data[(i * 4) + 1];
129 data->gamma_lut[i].b = gamma_data[(i * 4) + 2];
130 }
131
132 data->correction_matrix.resize(9);
133 for (int i = 0; i < 9; ++i) {
134 data->correction_matrix[i] =
135 qcms_transform_get_matrix(transform, i / 3, i % 3);
136 }
137
138 qcms_transform_release(transform);
139 qcms_profile_release(srgb_profile);
56 } 140 }
141
142 VLOG(1) << "ICC file successfully parsed";
57 qcms_profile_release(display_profile); 143 qcms_profile_release(display_profile);
58 VLOG(1) << "Gamma data successfully read from icc file";
59 return data; 144 return data;
60 } 145 }
61 146
62 } // namespace 147 } // namespace
63 148
64 DisplayColorManager::DisplayColorManager( 149 DisplayColorManager::DisplayColorManager(
65 ui::DisplayConfigurator* configurator, 150 ui::DisplayConfigurator* configurator,
66 base::SequencedWorkerPool* blocking_pool) 151 base::SequencedWorkerPool* blocking_pool)
67 : configurator_(configurator), 152 : configurator_(configurator),
68 blocking_pool_(blocking_pool), 153 blocking_pool_(blocking_pool),
(...skipping 14 matching lines...) Expand all
83 } else { 168 } else {
84 if (state->product_id() != ui::DisplaySnapshot::kInvalidProductID) 169 if (state->product_id() != ui::DisplaySnapshot::kInvalidProductID)
85 LoadCalibrationForDisplay(state); 170 LoadCalibrationForDisplay(state);
86 } 171 }
87 } 172 }
88 } 173 }
89 174
90 void DisplayColorManager::ApplyDisplayColorCalibration(int64_t display_id, 175 void DisplayColorManager::ApplyDisplayColorCalibration(int64_t display_id,
91 int64_t product_id) { 176 int64_t product_id) {
92 if (calibration_map_.find(product_id) != calibration_map_.end()) { 177 if (calibration_map_.find(product_id) != calibration_map_.end()) {
93 ColorCalibrationData* ramp = calibration_map_[product_id]; 178 ColorCalibrationData* data = calibration_map_[product_id];
94 if (!configurator_->SetGammaRamp(display_id, ramp->lut)) 179 if (!configurator_->SetColorCorrection(display_id, data->degamma_lut,
95 LOG(WARNING) << "Error applying gamma ramp"; 180 data->gamma_lut,
181 data->correction_matrix))
182 LOG(WARNING) << "Error applying color correction data";
96 } 183 }
97 } 184 }
98 185
99 void DisplayColorManager::LoadCalibrationForDisplay( 186 void DisplayColorManager::LoadCalibrationForDisplay(
100 const ui::DisplaySnapshot* display) { 187 const ui::DisplaySnapshot* display) {
101 DCHECK(thread_checker_.CalledOnValidThread()); 188 DCHECK(thread_checker_.CalledOnValidThread());
102 if (display->display_id() == gfx::Display::kInvalidDisplayID) { 189 if (display->display_id() == gfx::Display::kInvalidDisplayID) {
103 LOG(WARNING) << "Trying to load calibration data for invalid display id"; 190 LOG(WARNING) << "Trying to load calibration data for invalid display id";
104 return; 191 return;
105 } 192 }
106 193
107 quirks::QuirksManager::Get()->RequestIccProfilePath( 194 quirks::QuirksManager::Get()->RequestIccProfilePath(
108 display->product_id(), 195 display->product_id(),
109 base::Bind(&DisplayColorManager::FinishLoadCalibrationForDisplay, 196 base::Bind(&DisplayColorManager::FinishLoadCalibrationForDisplay,
110 weak_ptr_factory_.GetWeakPtr(), display->display_id(), 197 weak_ptr_factory_.GetWeakPtr(), display->display_id(),
111 display->product_id(), display->type())); 198 display->product_id(), display->has_color_correction_matrix(),
199 display->type()));
112 } 200 }
113 201
114 void DisplayColorManager::FinishLoadCalibrationForDisplay( 202 void DisplayColorManager::FinishLoadCalibrationForDisplay(
115 int64_t display_id, 203 int64_t display_id,
116 int64_t product_id, 204 int64_t product_id,
205 bool has_color_correction_matrix,
117 ui::DisplayConnectionType type, 206 ui::DisplayConnectionType type,
118 const base::FilePath& path, 207 const base::FilePath& path,
119 bool file_downloaded) { 208 bool file_downloaded) {
120 DCHECK(thread_checker_.CalledOnValidThread()); 209 DCHECK(thread_checker_.CalledOnValidThread());
121 std::string product_string = quirks::IdToHexString(product_id); 210 std::string product_string = quirks::IdToHexString(product_id);
122 if (path.empty()) { 211 if (path.empty()) {
123 VLOG(1) << "No ICC file found with product id: " << product_string 212 VLOG(1) << "No ICC file found with product id: " << product_string
124 << " for display id: " << display_id; 213 << " for display id: " << display_id;
125 return; 214 return;
126 } 215 }
127 216
128 if (file_downloaded && type == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) { 217 if (file_downloaded && type == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) {
129 VLOG(1) << "Downloaded ICC file with product id: " << product_string 218 VLOG(1) << "Downloaded ICC file with product id: " << product_string
130 << " for internal display id: " << display_id 219 << " for internal display id: " << display_id
131 << ". Profile will be applied on next startup."; 220 << ". Profile will be applied on next startup.";
132 return; 221 return;
133 } 222 }
134 223
135 VLOG(1) << "Loading ICC file " << path.value() 224 VLOG(1) << "Loading ICC file " << path.value()
136 << " for display id: " << display_id 225 << " for display id: " << display_id
137 << " with product id: " << product_string; 226 << " with product id: " << product_string;
138 227
139 base::PostTaskAndReplyWithResult( 228 base::PostTaskAndReplyWithResult(
140 blocking_pool_, FROM_HERE, base::Bind(&ParseDisplayProfile, path), 229 blocking_pool_, FROM_HERE,
230 base::Bind(&ParseDisplayProfile, path, has_color_correction_matrix),
141 base::Bind(&DisplayColorManager::UpdateCalibrationData, 231 base::Bind(&DisplayColorManager::UpdateCalibrationData,
142 weak_ptr_factory_.GetWeakPtr(), display_id, product_id)); 232 weak_ptr_factory_.GetWeakPtr(), display_id, product_id));
143 } 233 }
144 234
145 void DisplayColorManager::UpdateCalibrationData( 235 void DisplayColorManager::UpdateCalibrationData(
146 int64_t display_id, 236 int64_t display_id,
147 int64_t product_id, 237 int64_t product_id,
148 scoped_ptr<ColorCalibrationData> data) { 238 scoped_ptr<ColorCalibrationData> data) {
149 DCHECK(thread_checker_.CalledOnValidThread()); 239 DCHECK(thread_checker_.CalledOnValidThread());
150 if (data) { 240 if (data) {
151 // The map takes over ownership of the underlying memory. 241 // The map takes over ownership of the underlying memory.
152 calibration_map_[product_id] = data.release(); 242 calibration_map_[product_id] = data.release();
153 ApplyDisplayColorCalibration(display_id, product_id); 243 ApplyDisplayColorCalibration(display_id, product_id);
154 } 244 }
155 } 245 }
156 246
157 DisplayColorManager::ColorCalibrationData::ColorCalibrationData() {} 247 DisplayColorManager::ColorCalibrationData::ColorCalibrationData() {}
158 248
159 DisplayColorManager::ColorCalibrationData::~ColorCalibrationData() {} 249 DisplayColorManager::ColorCalibrationData::~ColorCalibrationData() {}
160 250
161 } // namespace ash 251 } // namespace ash
OLDNEW
« no previous file with comments | « ash/display/display_color_manager_chromeos.h ('k') | ash/display/display_color_manager_chromeos_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698