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

Side by Side Diff: ui/gfx/color_transform.cc

Issue 2769863003: cc: Add pixel tests for transfer function shaders (Closed)
Patch Set: Leave transfer substitutions unchanged Created 3 years, 9 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
« no previous file with comments | « cc/test/pixel_test.cc ('k') | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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 "ui/gfx/color_transform.h" 5 #include "ui/gfx/color_transform.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <list> 9 #include <list>
10 #include <memory> 10 #include <memory>
(...skipping 15 matching lines...) Expand all
26 #endif 26 #endif
27 27
28 using std::abs; 28 using std::abs;
29 using std::copysign; 29 using std::copysign;
30 using std::exp; 30 using std::exp;
31 using std::log; 31 using std::log;
32 using std::max; 32 using std::max;
33 using std::min; 33 using std::min;
34 using std::pow; 34 using std::pow;
35 using std::sqrt; 35 using std::sqrt;
36 using std::endl;
36 37
37 namespace gfx { 38 namespace gfx {
38 39
39 namespace { 40 namespace {
40 41
41 void InitStringStream(std::stringstream* ss) { 42 void InitStringStream(std::stringstream* ss) {
42 ss->imbue(std::locale::classic()); 43 ss->imbue(std::locale::classic());
43 ss->precision(8); 44 ss->precision(8);
44 *ss << std::scientific; 45 *ss << std::scientific;
45 } 46 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 return 1.0f + log(v) / log(10.0f) / 2.0f; 82 return 1.0f + log(v) / log(10.0f) / 2.0f;
82 83
83 case ColorSpace::TransferID::LOG_SQRT: 84 case ColorSpace::TransferID::LOG_SQRT:
84 if (v < sqrt(10.0f) / 1000.0f) 85 if (v < sqrt(10.0f) / 1000.0f)
85 return 0.0f; 86 return 0.0f;
86 return 1.0f + log(v) / log(10.0f) / 2.5f; 87 return 1.0f + log(v) / log(10.0f) / 2.5f;
87 88
88 case ColorSpace::TransferID::IEC61966_2_4: { 89 case ColorSpace::TransferID::IEC61966_2_4: {
89 float a = 1.099296826809442f; 90 float a = 1.099296826809442f;
90 float b = 0.018053968510807f; 91 float b = 0.018053968510807f;
91 if (v < -b) { 92 if (v < -b)
92 return -a * pow(-v, 0.45f) + (a - 1.0f); 93 return -a * pow(-v, 0.45f) + (a - 1.0f);
93 } else if (v <= b) { 94 else if (v <= b)
94 return 4.5f * v; 95 return 4.5f * v;
95 } else { 96 return a * pow(v, 0.45f) - (a - 1.0f);
96 return a * pow(v, 0.45f) - (a - 1.0f);
97 }
98 } 97 }
99 98
100 case ColorSpace::TransferID::BT1361_ECG: { 99 case ColorSpace::TransferID::BT1361_ECG: {
101 float a = 1.099f; 100 float a = 1.099f;
102 float b = 0.018f; 101 float b = 0.018f;
103 float l = 0.0045f; 102 float l = 0.0045f;
104 if (v < -l) { 103 if (v < -l)
105 return -(a * pow(-4.0f * v, 0.45f) + (a - 1.0f)) / 4.0f; 104 return -(a * pow(-4.0f * v, 0.45f) + (a - 1.0f)) / 4.0f;
106 } else if (v <= b) { 105 else if (v <= b)
107 return 4.5f * v; 106 return 4.5f * v;
108 } else { 107 else
109 return a * pow(v, 0.45f) - (a - 1.0f); 108 return a * pow(v, 0.45f) - (a - 1.0f);
110 }
111 } 109 }
112 110
113 case ColorSpace::TransferID::SMPTEST2084: { 111 case ColorSpace::TransferID::SMPTEST2084: {
114 // Go from scRGB levels to 0-1. 112 // Go from scRGB levels to 0-1.
115 v *= 80.0f / 10000.0f; 113 v *= 80.0f / 10000.0f;
116 v = max(0.0f, v); 114 v = max(0.0f, v);
117 float m1 = (2610.0f / 4096.0f) / 4.0f; 115 float m1 = (2610.0f / 4096.0f) / 4.0f;
118 float m2 = (2523.0f / 4096.0f) * 128.0f; 116 float m2 = (2523.0f / 4096.0f) * 128.0f;
119 float c1 = 3424.0f / 4096.0f; 117 float c1 = 3424.0f / 4096.0f;
120 float c2 = (2413.0f / 4096.0f) * 32.0f; 118 float c2 = (2413.0f / 4096.0f) * 32.0f;
121 float c3 = (2392.0f / 4096.0f) * 32.0f; 119 float c3 = (2392.0f / 4096.0f) * 32.0f;
122 return pow((c1 + c2 * pow(v, m1)) / (1.0f + c3 * pow(v, m1)), m2); 120 return pow((c1 + c2 * pow(v, m1)) / (1.0f + c3 * pow(v, m1)), m2);
123 } 121 }
124 122
125 // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf 123 // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
126 case ColorSpace::TransferID::ARIB_STD_B67: { 124 case ColorSpace::TransferID::ARIB_STD_B67: {
127 const float a = 0.17883277f; 125 const float a = 0.17883277f;
128 const float b = 0.28466892f; 126 const float b = 0.28466892f;
129 const float c = 0.55991073f; 127 const float c = 0.55991073f;
130 v = max(0.0f, v); 128 v = max(0.0f, v);
131 if (v <= 1) 129 if (v <= 1)
132 return 0.5f * sqrt(v); 130 return 0.5f * sqrt(v);
133 else 131 return a * log(v - b) + c;
134 return a * log(v - b) + c;
135 } 132 }
136 133
137 default: 134 default:
138 // Handled by SkColorSpaceTransferFn. 135 // Handled by SkColorSpaceTransferFn.
139 break; 136 break;
140 } 137 }
141 NOTREACHED(); 138 NOTREACHED();
142 return 0; 139 return 0;
143 } 140 }
144 141
145 float ToLinear(ColorSpace::TransferID id, float v) { 142 float ToLinear(ColorSpace::TransferID id, float v) {
146 switch (id) { 143 switch (id) {
147 case ColorSpace::TransferID::LOG: 144 case ColorSpace::TransferID::LOG:
148 if (v < 0.0f) 145 if (v < 0.0f)
149 return 0.0f; 146 return 0.0f;
150 return pow(10.0f, (v - 1.0f) * 2.0f); 147 return pow(10.0f, (v - 1.0f) * 2.0f);
151 148
152 case ColorSpace::TransferID::LOG_SQRT: 149 case ColorSpace::TransferID::LOG_SQRT:
153 if (v < 0.0f) 150 if (v < 0.0f)
154 return 0.0f; 151 return 0.0f;
155 return pow(10.0f, (v - 1.0f) * 2.5f); 152 return pow(10.0f, (v - 1.0f) * 2.5f);
156 153
157 case ColorSpace::TransferID::IEC61966_2_4: { 154 case ColorSpace::TransferID::IEC61966_2_4: {
158 float a = 1.099296826809442f; 155 float a = 1.099296826809442f;
159 float b = 0.018053968510807f; 156 // Equal to FromLinear(ColorSpace::TransferID::IEC61966_2_4, -a).
160 if (v < FromLinear(ColorSpace::TransferID::IEC61966_2_4, -a)) { 157 float from_linear_neg_a = -1.047844f;
158 // Equal to FromLinear(ColorSpace::TransferID::IEC61966_2_4, b).
159 float from_linear_b = 0.081243f;
160 if (v < from_linear_neg_a)
161 return -pow((a - 1.0f - v) / a, 1.0f / 0.45f); 161 return -pow((a - 1.0f - v) / a, 1.0f / 0.45f);
162 } else if (v <= FromLinear(ColorSpace::TransferID::IEC61966_2_4, b)) { 162 else if (v <= from_linear_b)
163 return v / 4.5f; 163 return v / 4.5f;
164 } else { 164 return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
165 return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
166 }
167 } 165 }
168 166
169 case ColorSpace::TransferID::BT1361_ECG: { 167 case ColorSpace::TransferID::BT1361_ECG: {
170 float a = 1.099f; 168 float a = 1.099f;
171 float b = 0.018f; 169 // Equal to FromLinear(ColorSpace::TransferID::BT1361_ECG, -l).
172 float l = 0.0045f; 170 float from_linear_neg_l = -0.020250f;
173 if (v < FromLinear(ColorSpace::TransferID::BT1361_ECG, -l)) { 171 // Equal to FromLinear(ColorSpace::TransferID::BT1361_ECG, b).
172 float from_linear_b = 0.081000f;
173 if (v < from_linear_neg_l)
174 return -pow((1.0f - a - v * 4.0f) / a, 1.0f / 0.45f) / 4.0f; 174 return -pow((1.0f - a - v * 4.0f) / a, 1.0f / 0.45f) / 4.0f;
175 } else if (v <= FromLinear(ColorSpace::TransferID::BT1361_ECG, b)) { 175 else if (v <= from_linear_b)
176 return v / 4.5f; 176 return v / 4.5f;
177 } else { 177 return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
178 return pow((v + a - 1.0f) / a, 1.0f / 0.45f);
179 }
180 } 178 }
181 179
182 case ColorSpace::TransferID::SMPTEST2084: { 180 case ColorSpace::TransferID::SMPTEST2084: {
183 v = max(0.0f, v); 181 v = max(0.0f, v);
184 float m1 = (2610.0f / 4096.0f) / 4.0f; 182 float m1 = (2610.0f / 4096.0f) / 4.0f;
185 float m2 = (2523.0f / 4096.0f) * 128.0f; 183 float m2 = (2523.0f / 4096.0f) * 128.0f;
186 float c1 = 3424.0f / 4096.0f; 184 float c1 = 3424.0f / 4096.0f;
187 float c2 = (2413.0f / 4096.0f) * 32.0f; 185 float c2 = (2413.0f / 4096.0f) * 32.0f;
188 float c3 = (2392.0f / 4096.0f) * 32.0f; 186 float c3 = (2392.0f / 4096.0f) * 32.0f;
189 v = pow(max(pow(v, 1.0f / m2) - c1, 0.0f) / (c2 - c3 * pow(v, 1.0f / m2)), 187 v = pow(max(pow(v, 1.0f / m2) - c1, 0.0f) / (c2 - c3 * pow(v, 1.0f / m2)),
190 1.0f / m1); 188 1.0f / m1);
191 // This matches the scRGB definition that 1.0 means 80 nits. 189 // This matches the scRGB definition that 1.0 means 80 nits.
192 // TODO(hubbe): It would be *nice* if 1.0 meant more than that, but 190 // TODO(hubbe): It would be *nice* if 1.0 meant more than that, but
193 // that might be difficult to do right now. 191 // that might be difficult to do right now.
194 v *= 10000.0f / 80.0f; 192 v *= 10000.0f / 80.0f;
195 return v; 193 return v;
196 } 194 }
197 195
198 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: 196 case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
199 v = max(0.0f, v); 197 v = max(0.0f, v);
200 return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f); 198 return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f);
201 199
202 // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf 200 // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
203 case ColorSpace::TransferID::ARIB_STD_B67: { 201 case ColorSpace::TransferID::ARIB_STD_B67: {
204 v = max(0.0f, v); 202 v = max(0.0f, v);
205 const float a = 0.17883277f; 203 const float a = 0.17883277f;
206 const float b = 0.28466892f; 204 const float b = 0.28466892f;
207 const float c = 0.55991073f; 205 const float c = 0.55991073f;
208 float v_ = 0.0f; 206 if (v <= 0.5f)
209 if (v <= 0.5f) { 207 return (v * 2.0f) * (v * 2.0f);
210 v_ = (v * 2.0f) * (v * 2.0f); 208 return exp((v - c) / a) + b;
211 } else {
212 v_ = exp((v - c) / a) + b;
213 }
214 return v_;
215 } 209 }
216 210
217 default: 211 default:
218 // Handled by SkColorSpaceTransferFn. 212 // Handled by SkColorSpaceTransferFn.
219 break; 213 break;
220 } 214 }
221 NOTREACHED(); 215 NOTREACHED();
222 return 0; 216 return 0;
223 } 217 }
224 218
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 258
265 // Join methods, returns true if the |next| transform was successfully 259 // Join methods, returns true if the |next| transform was successfully
266 // assimilated into |this|. 260 // assimilated into |this|.
267 // If Join() returns true, |next| is no longer needed and can be deleted. 261 // If Join() returns true, |next| is no longer needed and can be deleted.
268 virtual bool Join(ColorTransformStep* next) { return false; } 262 virtual bool Join(ColorTransformStep* next) { return false; }
269 263
270 // Return true if this is a null transform. 264 // Return true if this is a null transform.
271 virtual bool IsNull() { return false; } 265 virtual bool IsNull() { return false; }
272 virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0; 266 virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0;
273 virtual bool CanAppendShaderSource() { return false; } 267 virtual bool CanAppendShaderSource() { return false; }
274 virtual void AppendShaderSource(std::stringstream* result) { NOTREACHED(); } 268 // In the shader, |hdr| will appear before |src|, so any helper functions that
269 // are created should be put in |hdr|. Any helper functions should have
270 // |step_index| included in the function name, to ensure that there are no
271 // naming conflicts.
272 virtual void AppendShaderSource(std::stringstream* hdr,
273 std::stringstream* src,
274 size_t step_index) const {
275 NOTREACHED();
276 }
275 277
276 private: 278 private:
277 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); 279 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep);
278 }; 280 };
279 281
280 class ColorTransformInternal : public ColorTransform { 282 class ColorTransformInternal : public ColorTransform {
281 public: 283 public:
282 ColorTransformInternal(const ColorSpace& from, 284 ColorTransformInternal(const ColorSpace& from,
283 const ColorSpace& to, 285 const ColorSpace& to,
284 Intent intent); 286 Intent intent);
(...skipping 26 matching lines...) Expand all
311 gfx::ColorSpace src_; 313 gfx::ColorSpace src_;
312 gfx::ColorSpace dst_; 314 gfx::ColorSpace dst_;
313 }; 315 };
314 316
315 class ColorTransformNull : public ColorTransformStep { 317 class ColorTransformNull : public ColorTransformStep {
316 public: 318 public:
317 ColorTransformNull* GetNull() override { return this; } 319 ColorTransformNull* GetNull() override { return this; }
318 bool IsNull() override { return true; } 320 bool IsNull() override { return true; }
319 void Transform(ColorTransform::TriStim* color, size_t num) const override {} 321 void Transform(ColorTransform::TriStim* color, size_t num) const override {}
320 bool CanAppendShaderSource() override { return true; } 322 bool CanAppendShaderSource() override { return true; }
321 void AppendShaderSource(std::stringstream* result) override {} 323 void AppendShaderSource(std::stringstream* hdr,
324 std::stringstream* src,
325 size_t step_index) const override {}
322 }; 326 };
323 327
324 class ColorTransformMatrix : public ColorTransformStep { 328 class ColorTransformMatrix : public ColorTransformStep {
325 public: 329 public:
326 explicit ColorTransformMatrix(const class Transform& matrix) 330 explicit ColorTransformMatrix(const class Transform& matrix)
327 : matrix_(matrix) {} 331 : matrix_(matrix) {}
328 ColorTransformMatrix* GetMatrix() override { return this; } 332 ColorTransformMatrix* GetMatrix() override { return this; }
329 bool Join(ColorTransformStep* next_untyped) override { 333 bool Join(ColorTransformStep* next_untyped) override {
330 ColorTransformMatrix* next = next_untyped->GetMatrix(); 334 ColorTransformMatrix* next = next_untyped->GetMatrix();
331 if (!next) 335 if (!next)
332 return false; 336 return false;
333 class Transform tmp = next->matrix_; 337 class Transform tmp = next->matrix_;
334 tmp *= matrix_; 338 tmp *= matrix_;
335 matrix_ = tmp; 339 matrix_ = tmp;
336 return true; 340 return true;
337 } 341 }
338 342
339 bool IsNull() override { 343 bool IsNull() override {
340 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); 344 return SkMatrixIsApproximatelyIdentity(matrix_.matrix());
341 } 345 }
342 346
343 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 347 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
344 for (size_t i = 0; i < num; i++) 348 for (size_t i = 0; i < num; i++)
345 matrix_.TransformPoint(colors + i); 349 matrix_.TransformPoint(colors + i);
346 } 350 }
347 351
348 bool CanAppendShaderSource() override { return true; } 352 bool CanAppendShaderSource() override { return true; }
349 353
350 void AppendShaderSource(std::stringstream* result) override { 354 void AppendShaderSource(std::stringstream* hdr,
355 std::stringstream* src,
356 size_t step_index) const override {
351 const SkMatrix44& m = matrix_.matrix(); 357 const SkMatrix44& m = matrix_.matrix();
352 *result << " color = mat3("; 358 *src << " color = mat3(";
353 *result << m.get(0, 0) << ", " << m.get(1, 0) << ", " << m.get(2, 0) << ","; 359 *src << m.get(0, 0) << ", " << m.get(1, 0) << ", " << m.get(2, 0) << ",";
354 *result << std::endl; 360 *src << endl;
355 *result << " "; 361 *src << " ";
356 *result << m.get(0, 1) << ", " << m.get(1, 1) << ", " << m.get(2, 1) << ","; 362 *src << m.get(0, 1) << ", " << m.get(1, 1) << ", " << m.get(2, 1) << ",";
357 *result << std::endl; 363 *src << endl;
358 *result << " "; 364 *src << " ";
359 *result << m.get(0, 2) << ", " << m.get(1, 2) << ", " << m.get(2, 2) << ")"; 365 *src << m.get(0, 2) << ", " << m.get(1, 2) << ", " << m.get(2, 2) << ")";
360 *result << " * color;" << std::endl; 366 *src << " * color;" << endl;
361 367
362 // Only print the translational component if it isn't the identity. 368 // Only print the translational component if it isn't the identity.
363 if (m.get(0, 3) != 0.f || m.get(1, 3) != 0.f || m.get(2, 3) != 0.f) { 369 if (m.get(0, 3) != 0.f || m.get(1, 3) != 0.f || m.get(2, 3) != 0.f) {
364 *result << " color += vec3("; 370 *src << " color += vec3(";
365 *result << m.get(0, 3) << ", " << m.get(1, 3) << ", " << m.get(2, 3); 371 *src << m.get(0, 3) << ", " << m.get(1, 3) << ", " << m.get(2, 3);
366 *result << ");" << std::endl; 372 *src << ");" << endl;
367 } 373 }
368 } 374 }
369 375
370 private: 376 private:
371 class Transform matrix_; 377 class Transform matrix_;
372 }; 378 };
373 379
374 class ColorTransformSkTransferFn : public ColorTransformStep { 380 class ColorTransformPerChannelTransferFn : public ColorTransformStep {
381 public:
382 explicit ColorTransformPerChannelTransferFn(bool extended)
383 : extended_(extended) {}
384
385 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
386 for (size_t i = 0; i < num; i++) {
387 ColorTransform::TriStim& c = colors[i];
388 if (extended_) {
389 c.set_x(copysign(Evaluate(abs(c.x())), c.x()));
390 c.set_y(copysign(Evaluate(abs(c.y())), c.y()));
391 c.set_z(copysign(Evaluate(abs(c.z())), c.z()));
392 } else {
393 c.set_x(Evaluate(c.x()));
394 c.set_y(Evaluate(c.y()));
395 c.set_z(Evaluate(c.z()));
396 }
397 }
398 }
399
400 void AppendShaderSource(std::stringstream* hdr,
401 std::stringstream* src,
402 size_t step_index) const override {
403 *hdr << "float TransferFn" << step_index << "(float v) {" << endl;
404 AppendTransferShaderSource(hdr);
405 *hdr << "}" << endl;
406 if (extended_) {
407 *src << " color.r = sign(color.r) * TransferFn" << step_index
408 << "(abs(color.r));" << endl;
409 *src << " color.g = sign(color.g) * TransferFn" << step_index
410 << "(abs(color.g));" << endl;
411 *src << " color.b = sign(color.b) * TransferFn" << step_index
412 << "(abs(color.b));" << endl;
413 } else {
414 *src << " color.r = TransferFn" << step_index << "(color.r);" << endl;
415 *src << " color.g = TransferFn" << step_index << "(color.g);" << endl;
416 *src << " color.b = TransferFn" << step_index << "(color.b);" << endl;
417 }
418 }
419
420 virtual float Evaluate(float x) const = 0;
421 // Populate the body of a shader function that takes a float v and returns
422 // Evaluate(v).
423 virtual void AppendTransferShaderSource(std::stringstream* src) const = 0;
424
425 protected:
426 // True if the transfer function is extended to be defined for all real
427 // values by point symmetry.
428 bool extended_ = false;
429 };
430
431 class ColorTransformSkTransferFn : public ColorTransformPerChannelTransferFn {
375 public: 432 public:
376 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn, 433 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn,
377 bool extended) 434 bool extended)
378 : fn_(fn), extended_(extended) {} 435 : ColorTransformPerChannelTransferFn(extended), fn_(fn) {}
436 // ColorTransformStep implementation.
379 ColorTransformSkTransferFn* GetSkTransferFn() override { return this; } 437 ColorTransformSkTransferFn* GetSkTransferFn() override { return this; }
380
381 bool Join(ColorTransformStep* next_untyped) override { 438 bool Join(ColorTransformStep* next_untyped) override {
382 ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn(); 439 ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn();
383 if (!next) 440 if (!next)
384 return false; 441 return false;
385 if (!extended_ && !next->extended_ && 442 if (!extended_ && !next->extended_ &&
386 SkTransferFnsApproximatelyCancel(fn_, next->fn_)) { 443 SkTransferFnsApproximatelyCancel(fn_, next->fn_)) {
387 // Set to be the identity. 444 // Set to be the identity.
388 fn_.fA = 1; 445 fn_.fA = 1;
389 fn_.fB = 0; 446 fn_.fB = 0;
390 fn_.fC = 1; 447 fn_.fC = 1;
391 fn_.fD = 0; 448 fn_.fD = 0;
392 fn_.fE = 0; 449 fn_.fE = 0;
393 fn_.fF = 0; 450 fn_.fF = 0;
394 fn_.fG = 1; 451 fn_.fG = 1;
395 return true; 452 return true;
396 } 453 }
397 return false; 454 return false;
398 } 455 }
399 456 bool CanAppendShaderSource() override { return true; }
400 bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); } 457 bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); }
401 458
402 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 459 // ColorTransformPerChannelTransferFn implementation:
403 for (size_t i = 0; i < num; i++) { 460 float Evaluate(float v) const override { return SkTransferFnEval(fn_, v); }
404 ColorTransform::TriStim& c = colors[i]; 461 void AppendTransferShaderSource(std::stringstream* result) const override {
405 if (extended_) {
406 c.set_x(copysign(SkTransferFnEval(fn_, abs(c.x())), c.x()));
407 c.set_y(copysign(SkTransferFnEval(fn_, abs(c.y())), c.y()));
408 c.set_z(copysign(SkTransferFnEval(fn_, abs(c.z())), c.z()));
409 } else {
410 c.set_x(SkTransferFnEval(fn_, c.x()));
411 c.set_y(SkTransferFnEval(fn_, c.y()));
412 c.set_z(SkTransferFnEval(fn_, c.z()));
413 }
414 }
415 }
416
417 bool CanAppendShaderSource() override { return true; }
418
419 void AppendShaderSourceChannel(std::stringstream* result,
420 const std::string& value) {
421 std::string abs_value = "abs(" + value + ")";
422 const float kEpsilon = 1.f / 1024.f; 462 const float kEpsilon = 1.f / 1024.f;
423 463
424 // Construct the linear segment 464 // Construct the linear segment
425 // linear = C * x + F 465 // linear = C * x + F
426 // Elide operations that will be close to the identity. 466 // Elide operations that will be close to the identity.
427 std::string linear = value; 467 std::string linear = "v";
428 if (std::abs(fn_.fC - 1.f) > kEpsilon) 468 if (std::abs(fn_.fC - 1.f) > kEpsilon)
429 linear = Str(fn_.fC) + " * " + linear; 469 linear = Str(fn_.fC) + " * " + linear;
430 if (std::abs(fn_.fF) > kEpsilon) 470 if (std::abs(fn_.fF) > kEpsilon)
431 linear = linear + " + " + Str(fn_.fF); 471 linear = linear + " + " + Str(fn_.fF);
432 472
433 // Construct the nonlinear segment. 473 // Construct the nonlinear segment.
434 // nonlinear = pow(A * x + B, G) + E 474 // nonlinear = pow(A * x + B, G) + E
435 // Elide operations (especially the pow) that will be close to the 475 // Elide operations (especially the pow) that will be close to the
436 // identity. 476 // identity.
437 std::string nonlinear = extended_ ? abs_value : value; 477 std::string nonlinear = "v";
438 if (std::abs(fn_.fA - 1.f) > kEpsilon) 478 if (std::abs(fn_.fA - 1.f) > kEpsilon)
439 nonlinear = Str(fn_.fA) + " * " + nonlinear; 479 nonlinear = Str(fn_.fA) + " * " + nonlinear;
440 if (std::abs(fn_.fB) > kEpsilon) 480 if (std::abs(fn_.fB) > kEpsilon)
441 nonlinear = nonlinear + " + " + Str(fn_.fB); 481 nonlinear = nonlinear + " + " + Str(fn_.fB);
442 if (std::abs(fn_.fG - 1.f) > kEpsilon) 482 if (std::abs(fn_.fG - 1.f) > kEpsilon)
443 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")"; 483 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")";
444 if (std::abs(fn_.fE) > kEpsilon) 484 if (std::abs(fn_.fE) > kEpsilon)
445 nonlinear = nonlinear + " + " + Str(fn_.fE); 485 nonlinear = nonlinear + " + " + Str(fn_.fE);
446 if (extended_) { 486
447 if (nonlinear == abs_value) 487 // Add both parts, skipping the if clause if possible.
448 nonlinear = value; 488 if (fn_.fD > kEpsilon) {
449 else 489 *result << " if (v < " << Str(fn_.fD) << ")" << endl;
450 nonlinear = "sign(" + value + ") * (" + nonlinear + ")"; 490 *result << " return " << linear << ";" << endl;
491 *result << " return " << nonlinear << ";" << endl;
492 } else {
493 *result << " return " << nonlinear << ";" << endl;
451 } 494 }
452
453 // Add both parts, skpping the if clause if possible.
454 if (fn_.fD > kEpsilon) {
455 if (extended_) {
456 *result << " if (" << abs_value << " < " << Str(fn_.fD) << ")"
457 << std::endl;
458 } else {
459 *result << " if (" << value << " < " << Str(fn_.fD) << ")"
460 << std::endl;
461 }
462 *result << " " << value << " = " << linear << ";" << std::endl;
463 *result << " else" << std::endl;
464 *result << " " << value << " = " << nonlinear << ";" << std::endl;
465 } else {
466 *result << " " << value << " = " << nonlinear << ";" << std::endl;
467 }
468 }
469
470 void AppendShaderSource(std::stringstream* result) override {
471 // Append the transfer function for each channel.
472 AppendShaderSourceChannel(result, "color.r");
473 AppendShaderSourceChannel(result, "color.g");
474 AppendShaderSourceChannel(result, "color.b");
475 } 495 }
476 496
477 private: 497 private:
478 SkColorSpaceTransferFn fn_; 498 SkColorSpaceTransferFn fn_;
479 // True if the transfer function is extended to be defined for all real
480 // values.
481 const bool extended_ = false;
482 }; 499 };
483 500
484 class ColorTransformFromLinear : public ColorTransformStep { 501 class ColorTransformFromLinear : public ColorTransformPerChannelTransferFn {
485 public: 502 public:
503 // ColorTransformStep implementation.
486 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer) 504 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer)
487 : transfer_(transfer) {} 505 : ColorTransformPerChannelTransferFn(false), transfer_(transfer) {}
488 ColorTransformFromLinear* GetFromLinear() override { return this; } 506 ColorTransformFromLinear* GetFromLinear() override { return this; }
507 bool CanAppendShaderSource() override { return true; }
489 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } 508 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }
490 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 509
491 for (size_t i = 0; i < num; i++) { 510 // ColorTransformPerChannelTransferFn implementation:
492 colors[i].set_x(FromLinear(transfer_, colors[i].x())); 511 float Evaluate(float v) const override { return FromLinear(transfer_, v); }
493 colors[i].set_y(FromLinear(transfer_, colors[i].y())); 512 void AppendTransferShaderSource(std::stringstream* src) const override {
494 colors[i].set_z(FromLinear(transfer_, colors[i].z())); 513 // This is a string-ized copy-paste from FromLinear.
514 switch (transfer_) {
515 case ColorSpace::TransferID::LOG:
516 *src << " if (v < 0.01)\n"
517 " return 0.0;\n"
518 " return 1.0 + log(v) / log(10.0) / 2.0;\n";
519 return;
520 case ColorSpace::TransferID::LOG_SQRT:
521 *src << " if (v < sqrt(10.0) / 1000.0)\n"
522 " return 0.0;\n"
523 " return 1.0 + log(v) / log(10.0) / 2.5;\n";
524 return;
525 case ColorSpace::TransferID::IEC61966_2_4:
526 *src << " float a = 1.099296826809442;\n"
527 " float b = 0.018053968510807;\n"
528 " if (v < -b)\n"
529 " return -a * pow(-v, 0.45) + (a - 1.0);\n"
530 " else if (v <= b)\n"
531 " return 4.5 * v;\n"
532 " return a * pow(v, 0.45) - (a - 1.0);\n";
533 return;
534 case ColorSpace::TransferID::BT1361_ECG:
535 *src << " float a = 1.099;\n"
536 " float b = 0.018;\n"
537 " float l = 0.0045;\n"
538 " if (v < -l)\n"
539 " return -(a * pow(-4.0 * v, 0.45) + (a - 1.0)) / 4.0;\n"
540 " else if (v <= b)\n"
541 " return 4.5 * v;\n"
542 " return a * pow(v, 0.45) - (a - 1.0);\n";
543 return;
544 case ColorSpace::TransferID::SMPTEST2084:
545 *src << " v *= 80.0 / 10000.0;\n"
546 " v = max(0.0, v);\n"
547 " float m1 = (2610.0 / 4096.0) / 4.0;\n"
548 " float m2 = (2523.0 / 4096.0) * 128.0;\n"
549 " float c1 = 3424.0 / 4096.0;\n"
550 " float c2 = (2413.0 / 4096.0) * 32.0;\n"
551 " float c3 = (2392.0 / 4096.0) * 32.0;\n"
552 " return pow((c1 + c2 * pow(v, m1)) / \n"
553 " (1.0 + c3 * pow(v, m1)), m2);\n";
554 return;
555 case ColorSpace::TransferID::ARIB_STD_B67:
556 *src << " const float a = 0.17883277;\n"
557 " const float b = 0.28466892;\n"
558 " const float c = 0.55991073;\n"
559 " v = max(0.0, v);\n"
560 " if (v <= 1.0)\n"
561 " return 0.5 * sqrt(v);\n"
562 " return a * log(v - b) + c;\n";
563 return;
564 default:
565 break;
495 } 566 }
567 NOTREACHED();
496 } 568 }
497 569
498 private: 570 private:
499 friend class ColorTransformToLinear; 571 friend class ColorTransformToLinear;
500 ColorSpace::TransferID transfer_; 572 ColorSpace::TransferID transfer_;
501 }; 573 };
502 574
503 class ColorTransformToLinear : public ColorTransformStep { 575 class ColorTransformToLinear : public ColorTransformPerChannelTransferFn {
504 public: 576 public:
505 explicit ColorTransformToLinear(ColorSpace::TransferID transfer) 577 explicit ColorTransformToLinear(ColorSpace::TransferID transfer)
506 : transfer_(transfer) {} 578 : ColorTransformPerChannelTransferFn(false), transfer_(transfer) {}
507 579 // ColorTransformStep implementation:
508 bool Join(ColorTransformStep* next_untyped) override { 580 bool Join(ColorTransformStep* next_untyped) override {
509 ColorTransformFromLinear* next = next_untyped->GetFromLinear(); 581 ColorTransformFromLinear* next = next_untyped->GetFromLinear();
510 if (!next) 582 if (!next)
511 return false; 583 return false;
512 if (transfer_ == next->transfer_) { 584 if (transfer_ == next->transfer_) {
513 transfer_ = ColorSpace::TransferID::LINEAR; 585 transfer_ = ColorSpace::TransferID::LINEAR;
514 return true; 586 return true;
515 } 587 }
516 return false; 588 return false;
517 } 589 }
518 590 bool CanAppendShaderSource() override { return true; }
519 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } 591 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }
520 592
593 // ColorTransformPerChannelTransferFn implementation:
594 float Evaluate(float v) const override { return ToLinear(transfer_, v); }
595 void AppendTransferShaderSource(std::stringstream* src) const override {
596 // This is a string-ized copy-paste from ToLinear.
597 switch (transfer_) {
598 case ColorSpace::TransferID::LOG:
599 *src << " if (v < 0.0)\n"
600 " return 0.0;\n"
601 " return pow(10.0, (v - 1.0) * 2.0);\n";
602 return;
603 case ColorSpace::TransferID::LOG_SQRT:
604 *src << " if (v < 0.0)\n"
605 " return 0.0;\n"
606 " return pow(10.0, (v - 1.0) * 2.5);\n";
607 return;
608 case ColorSpace::TransferID::IEC61966_2_4:
609 *src << " float a = 1.099296826809442;\n"
610 " float from_linear_neg_a = -1.047844;\n"
611 " float from_linear_b = 0.081243;\n"
612 " if (v < from_linear_neg_a)\n"
613 " return -pow((a - 1.0 - v) / a, 1.0 / 0.45);\n"
614 " else if (v <= from_linear_b)\n"
615 " return v / 4.5;\n"
616 " return pow((v + a - 1.0) / a, 1.0 / 0.45);\n";
617 return;
618 case ColorSpace::TransferID::BT1361_ECG:
619 *src << " float a = 1.099;\n"
620 " float from_linear_neg_l = -0.020250;\n"
621 " float from_linear_b = 0.081000;\n"
622 " if (v < from_linear_neg_l)\n"
623 " return -pow((1.0 - a - v * 4.0) / a, 1.0 / 0.45) / 4.0;\n"
624 " else if (v <= from_linear_b)\n"
625 " return v / 4.5;\n"
626 " return pow((v + a - 1.0) / a, 1.0 / 0.45);\n";
627 return;
628 case ColorSpace::TransferID::SMPTEST2084:
629 *src << " v = max(0.0, v);\n"
630 " float m1 = (2610.0 / 4096.0) / 4.0;\n"
631 " float m2 = (2523.0 / 4096.0) * 128.0;\n"
632 " float c1 = 3424.0 / 4096.0;\n"
633 " float c2 = (2413.0 / 4096.0) * 32.0;\n"
634 " float c3 = (2392.0 / 4096.0) * 32.0;\n"
635 " v = pow(max(pow(v, 1.0 / m2) - c1, 0.0) /\n"
636 " (c2 - c3 * pow(v, 1.0 / m2)), 1.0 / m1);\n"
637 " v *= 10000.0 / 80.0;\n"
638 " return v;\n";
639 return;
640 case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
641 *src << " v = max(0.0, v);\n"
642 " return min(2.3 * pow(v, 2.8), v / 5.0 + 0.8);\n";
643 return;
644 case ColorSpace::TransferID::ARIB_STD_B67:
645 *src << " v = max(0.0, v);\n"
646 " float a = 0.17883277;\n"
647 " float b = 0.28466892;\n"
648 " float c = 0.55991073;\n"
649 " if (v <= 0.5)\n"
650 " return (v * 2.0) * (v * 2.0);\n"
651 " return exp((v - c) / a) + b;\n";
652 return;
653 default:
654 break;
655 }
656 NOTREACHED();
657 }
658
659 private:
660 ColorSpace::TransferID transfer_;
661 };
662
663 class ColorTransformSMPTEST2048NonHdrToLinear : public ColorTransformStep {
664 public:
521 // Assumes BT2020 primaries. 665 // Assumes BT2020 primaries.
522 static float Luma(const ColorTransform::TriStim& c) { 666 static float Luma(const ColorTransform::TriStim& c) {
523 return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; 667 return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f;
524 } 668 }
525
526 static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) { 669 static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim& c) {
527 float maximum = max(max(c.x(), c.y()), c.z()); 670 float maximum = max(max(c.x(), c.y()), c.z());
528 if (maximum > 1.0f) { 671 if (maximum > 1.0f) {
529 float l = Luma(c); 672 float l = Luma(c);
530 c.Scale(1.0f / maximum); 673 c.Scale(1.0f / maximum);
531 ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); 674 ColorTransform::TriStim white(1.0f, 1.0f, 1.0f);
532 white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); 675 white.Scale((1.0f - 1.0f / maximum) * l / Luma(white));
533 ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); 676 ColorTransform::TriStim black(0.0f, 0.0f, 0.0f);
534 c += white - black; 677 c += white - black;
535 } 678 }
536 return c; 679 return c;
537 } 680 }
538
539 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 681 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
540 if (transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) { 682 for (size_t i = 0; i < num; i++) {
541 for (size_t i = 0; i < num; i++) { 683 ColorTransform::TriStim ret(
542 ColorTransform::TriStim ret(ToLinear(transfer_, colors[i].x()), 684 ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].x()),
543 ToLinear(transfer_, colors[i].y()), 685 ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].y()),
544 ToLinear(transfer_, colors[i].z())); 686 ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].z()));
545 if (Luma(ret) > 0.0) { 687 if (Luma(ret) > 0.0) {
546 ColorTransform::TriStim smpte2084( 688 ColorTransform::TriStim smpte2084(
547 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()), 689 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()),
548 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()), 690 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()),
549 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z())); 691 ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z()));
550 smpte2084.Scale(Luma(ret) / Luma(smpte2084)); 692 smpte2084.Scale(Luma(ret) / Luma(smpte2084));
551 ret = ClipToWhite(smpte2084); 693 ret = ClipToWhite(smpte2084);
552 }
553 colors[i] = ret;
554 } 694 }
555 } else { 695 colors[i] = ret;
556 for (size_t i = 0; i < num; i++) {
557 colors[i].set_x(ToLinear(transfer_, colors[i].x()));
558 colors[i].set_y(ToLinear(transfer_, colors[i].y()));
559 colors[i].set_z(ToLinear(transfer_, colors[i].z()));
560 }
561 } 696 }
562 } 697 }
563
564 private:
565 ColorSpace::TransferID transfer_;
566 }; 698 };
567 699
568 // BT2020 Constant Luminance is different than most other 700 // BT2020 Constant Luminance is different than most other
569 // ways to encode RGB values as YUV. The basic idea is that 701 // ways to encode RGB values as YUV. The basic idea is that
570 // transfer functions are applied on the Y value instead of 702 // transfer functions are applied on the Y value instead of
571 // on the RGB values. However, running the transfer function 703 // on the RGB values. However, running the transfer function
572 // on the U and V values doesn't make any sense since they 704 // on the U and V values doesn't make any sense since they
573 // are centered at 0.5. To work around this, the transfer function 705 // are centered at 0.5. To work around this, the transfer function
574 // is applied to the Y, R and B values, and then the U and V 706 // is applied to the Y, R and B values, and then the U and V
575 // values are calculated from that. 707 // values are calculated from that.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 } 777 }
646 if (V <= 0) { 778 if (V <= 0) {
647 R_Y = V * (-2.0 * -0.8591); 779 R_Y = V * (-2.0 * -0.8591);
648 } else { 780 } else {
649 R_Y = V * (2.0 * 0.4969); 781 R_Y = V * (2.0 * 0.4969);
650 } 782 }
651 // Return an RYB value, later steps will fix it. 783 // Return an RYB value, later steps will fix it.
652 YUV[i] = ColorTransform::TriStim(R_Y + Y, YUV[i].x(), B_Y + Y); 784 YUV[i] = ColorTransform::TriStim(R_Y + Y, YUV[i].x(), B_Y + Y);
653 } 785 }
654 } 786 }
787 bool CanAppendShaderSource() override { return true; }
788 void AppendShaderSource(std::stringstream* hdr,
789 std::stringstream* src,
790 size_t step_index) const override {
791 *hdr << "vec3 BT2020_YUV_to_RYB_Step" << step_index << "(vec3 color) {"
792 << endl;
793 *hdr << " float Y = color.x;" << endl;
794 *hdr << " float U = color.y;" << endl;
795 *hdr << " float V = color.z;" << endl;
796 *hdr << " float B_Y = 0.0;" << endl;
797 *hdr << " float R_Y = 0.0;" << endl;
798 *hdr << " if (U <= 0.0) {" << endl;
799 *hdr << " B_Y = Y * (-2.0 * -0.9702);" << endl;
800 *hdr << " } else {" << endl;
801 *hdr << " B_Y = U * (2.0 * 0.7910);" << endl;
802 *hdr << " }" << endl;
803 *hdr << " if (V <= 0.0) {" << endl;
804 *hdr << " R_Y = V * (-2.0 * -0.8591);" << endl;
805 *hdr << " } else {" << endl;
806 *hdr << " R_Y = V * (2.0 * 0.4969);" << endl;
807 *hdr << " }" << endl;
808 *hdr << " return vec3(R_Y + Y, Y, B_Y + Y);" << endl;
809 *hdr << "}" << endl;
810
811 *src << " color.rgb = BT2020_YUV_to_RYB_Step" << step_index
812 << "(color.rgb);" << endl;
813 }
655 814
656 private: 815 private:
657 bool null_ = false; 816 bool null_ = false;
658 }; 817 };
659 818
660 void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform( 819 void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform(
661 ColorSpace from, 820 ColorSpace from,
662 const ColorSpace& to, 821 const ColorSpace& to,
663 ColorTransform::Intent intent) { 822 ColorTransform::Intent intent) {
664 if (intent == ColorTransform::Intent::INTENT_PERCEPTUAL) { 823 if (intent == ColorTransform::Intent::INTENT_PERCEPTUAL) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 // If the target color space is not defined, just apply the adjust and 865 // If the target color space is not defined, just apply the adjust and
707 // tranfer matrices. This path is used by YUV to RGB color conversion 866 // tranfer matrices. This path is used by YUV to RGB color conversion
708 // when full color conversion is not enabled. 867 // when full color conversion is not enabled.
709 if (!to.IsValid()) 868 if (!to.IsValid())
710 return; 869 return;
711 870
712 SkColorSpaceTransferFn to_linear_fn; 871 SkColorSpaceTransferFn to_linear_fn;
713 if (from.GetTransferFunction(&to_linear_fn)) { 872 if (from.GetTransferFunction(&to_linear_fn)) {
714 steps_.push_back(base::MakeUnique<ColorTransformSkTransferFn>( 873 steps_.push_back(base::MakeUnique<ColorTransformSkTransferFn>(
715 to_linear_fn, from.HasExtendedSkTransferFn())); 874 to_linear_fn, from.HasExtendedSkTransferFn()));
875 } else if (from.transfer_ == ColorSpace::TransferID::SMPTEST2084_NON_HDR) {
876 steps_.push_back(
877 base::MakeUnique<ColorTransformSMPTEST2048NonHdrToLinear>());
716 } else { 878 } else {
717 steps_.push_back(base::MakeUnique<ColorTransformToLinear>(from.transfer_)); 879 steps_.push_back(base::MakeUnique<ColorTransformToLinear>(from.transfer_));
718 } 880 }
719 881
720 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { 882 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
721 // BT2020 CL is a special case. 883 // BT2020 CL is a special case.
722 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); 884 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>());
723 } 885 }
724 steps_.push_back( 886 steps_.push_back(
725 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from))); 887 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from)));
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 if (dst_profile) { 1024 if (dst_profile) {
863 steps_.push_back(base::MakeUnique<QCMSColorTransform>( 1025 steps_.push_back(base::MakeUnique<QCMSColorTransform>(
864 GetXYZD50Profile(), std::move(dst_profile))); 1026 GetXYZD50Profile(), std::move(dst_profile)));
865 } 1027 }
866 1028
867 if (intent != Intent::TEST_NO_OPT) 1029 if (intent != Intent::TEST_NO_OPT)
868 Simplify(); 1030 Simplify();
869 } 1031 }
870 1032
871 std::string ColorTransformInternal::GetShaderSource() const { 1033 std::string ColorTransformInternal::GetShaderSource() const {
872 std::stringstream result; 1034 std::stringstream hdr;
873 InitStringStream(&result); 1035 std::stringstream src;
874 result << "vec3 DoColorConversion(vec3 color) {" << std::endl; 1036 InitStringStream(&hdr);
1037 InitStringStream(&src);
1038 src << "vec3 DoColorConversion(vec3 color) {" << endl;
1039 size_t step_index = 0;
875 for (const auto& step : steps_) 1040 for (const auto& step : steps_)
876 step->AppendShaderSource(&result); 1041 step->AppendShaderSource(&hdr, &src, step_index++);
877 result << " return color;" << std::endl; 1042 src << " return color;" << endl;
878 result << "}" << std::endl; 1043 src << "}" << endl;
879 return result.str(); 1044 return hdr.str() + src.str();
880 } 1045 }
881 1046
882 bool ColorTransformInternal::CanGetShaderSource() const { 1047 bool ColorTransformInternal::CanGetShaderSource() const {
883 for (const auto& step : steps_) { 1048 for (const auto& step : steps_) {
884 if (!step->CanAppendShaderSource()) 1049 if (!step->CanAppendShaderSource())
885 return false; 1050 return false;
886 } 1051 }
887 return true; 1052 return true;
888 } 1053 }
889 1054
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 const ColorSpace& to, 1091 const ColorSpace& to,
927 Intent intent) { 1092 Intent intent) {
928 return std::unique_ptr<ColorTransform>( 1093 return std::unique_ptr<ColorTransform>(
929 new ColorTransformInternal(from, to, intent)); 1094 new ColorTransformInternal(from, to, intent));
930 } 1095 }
931 1096
932 ColorTransform::ColorTransform() {} 1097 ColorTransform::ColorTransform() {}
933 ColorTransform::~ColorTransform() {} 1098 ColorTransform::~ColorTransform() {}
934 1099
935 } // namespace gfx 1100 } // namespace gfx
OLDNEW
« no previous file with comments | « cc/test/pixel_test.cc ('k') | ui/gfx/color_transform_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698