OLD | NEW |
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> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" |
14 #include "third_party/qcms/src/qcms.h" | 15 #include "third_party/qcms/src/qcms.h" |
15 #include "ui/gfx/color_space.h" | 16 #include "ui/gfx/color_space.h" |
16 #include "ui/gfx/icc_profile.h" | 17 #include "ui/gfx/icc_profile.h" |
17 #include "ui/gfx/skia_color_space_util.h" | 18 #include "ui/gfx/skia_color_space_util.h" |
18 #include "ui/gfx/transform.h" | 19 #include "ui/gfx/transform.h" |
19 | 20 |
20 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H | 21 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H |
21 extern "C" { | 22 extern "C" { |
22 #include "third_party/qcms/src/chain.h" | 23 #include "third_party/qcms/src/chain.h" |
23 }; | 24 }; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 virtual ColorTransformNull* GetNull() { return nullptr; } | 244 virtual ColorTransformNull* GetNull() { return nullptr; } |
244 virtual QCMSColorTransform* GetQCMS() { return nullptr; } | 245 virtual QCMSColorTransform* GetQCMS() { return nullptr; } |
245 | 246 |
246 // Join methods, returns true if the |next| transform was successfully | 247 // Join methods, returns true if the |next| transform was successfully |
247 // assimilated into |this|. | 248 // assimilated into |this|. |
248 // If Join() returns true, |next| is no longer needed and can be deleted. | 249 // If Join() returns true, |next| is no longer needed and can be deleted. |
249 virtual bool Join(ColorTransformStep* next) { return false; } | 250 virtual bool Join(ColorTransformStep* next) { return false; } |
250 | 251 |
251 // Return true if this is a null transform. | 252 // Return true if this is a null transform. |
252 virtual bool IsNull() { return false; } | 253 virtual bool IsNull() { return false; } |
253 | |
254 virtual void Transform(ColorTransform::TriStim* color, size_t num) = 0; | 254 virtual void Transform(ColorTransform::TriStim* color, size_t num) = 0; |
| 255 virtual bool CanAppendShaderSource() { return false; } |
| 256 virtual void AppendShaderSource(std::string* result) { NOTREACHED(); } |
255 | 257 |
256 private: | 258 private: |
257 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); | 259 DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); |
258 }; | 260 }; |
259 | 261 |
260 class ColorTransformInternal : public ColorTransform { | 262 class ColorTransformInternal : public ColorTransform { |
261 public: | 263 public: |
262 ColorTransformInternal(const ColorSpace& from, | 264 ColorTransformInternal(const ColorSpace& from, |
263 const ColorSpace& to, | 265 const ColorSpace& to, |
264 Intent intent); | 266 Intent intent); |
265 ~ColorTransformInternal() override; | 267 ~ColorTransformInternal() override; |
266 | 268 |
267 // Perform transformation of colors, |colors| is both input and output. | |
268 void Transform(TriStim* colors, size_t num) override { | 269 void Transform(TriStim* colors, size_t num) override { |
269 for (const auto& step : steps_) | 270 for (const auto& step : steps_) |
270 step->Transform(colors, num); | 271 step->Transform(colors, num); |
271 } | 272 } |
| 273 bool CanGetShaderSource() const override; |
| 274 std::string GetShaderSource() const override; |
| 275 bool IsIdentity() const override { return steps_.empty(); } |
272 size_t NumberOfStepsForTesting() const override { return steps_.size(); } | 276 size_t NumberOfStepsForTesting() const override { return steps_.size(); } |
273 | 277 |
274 private: | 278 private: |
275 void AppendColorSpaceToColorSpaceTransform(ColorSpace from, | 279 void AppendColorSpaceToColorSpaceTransform(ColorSpace from, |
276 const ColorSpace& to, | 280 const ColorSpace& to, |
277 ColorTransform::Intent intent); | 281 ColorTransform::Intent intent); |
278 void Simplify(); | 282 void Simplify(); |
279 | 283 |
280 // Retrieve the ICC profile from which |color_space| was created, only if that | 284 // Retrieve the ICC profile from which |color_space| was created, only if that |
281 // is a more precise representation of the color space than the primaries and | 285 // is a more precise representation of the color space than the primaries and |
282 // transfer function in |color_space|. | 286 // transfer function in |color_space|. |
283 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space); | 287 ScopedQcmsProfile GetQCMSProfileIfNecessary(const ColorSpace& color_space); |
284 | 288 |
285 std::list<std::unique_ptr<ColorTransformStep>> steps_; | 289 std::list<std::unique_ptr<ColorTransformStep>> steps_; |
286 }; | 290 }; |
287 | 291 |
| 292 #define SRC(...) \ |
| 293 do { \ |
| 294 *result += std::string(" ") + base::StringPrintf(__VA_ARGS__) + \ |
| 295 std::string("\n"); \ |
| 296 } while (0) |
| 297 |
288 class ColorTransformNull : public ColorTransformStep { | 298 class ColorTransformNull : public ColorTransformStep { |
289 public: | 299 public: |
290 ColorTransformNull* GetNull() override { return this; } | 300 ColorTransformNull* GetNull() override { return this; } |
291 bool IsNull() override { return true; } | 301 bool IsNull() override { return true; } |
292 void Transform(ColorTransform::TriStim* color, size_t num) override {} | 302 void Transform(ColorTransform::TriStim* color, size_t num) override {} |
| 303 bool CanAppendShaderSource() override { return true; } |
| 304 void AppendShaderSource(std::string* result) override {} |
293 }; | 305 }; |
294 | 306 |
295 class ColorTransformMatrix : public ColorTransformStep { | 307 class ColorTransformMatrix : public ColorTransformStep { |
296 public: | 308 public: |
297 explicit ColorTransformMatrix(const class Transform& matrix) | 309 explicit ColorTransformMatrix(const class Transform& matrix) |
298 : matrix_(matrix) {} | 310 : matrix_(matrix) {} |
299 ColorTransformMatrix* GetMatrix() override { return this; } | 311 ColorTransformMatrix* GetMatrix() override { return this; } |
300 bool Join(ColorTransformStep* next_untyped) override { | 312 bool Join(ColorTransformStep* next_untyped) override { |
301 ColorTransformMatrix* next = next_untyped->GetMatrix(); | 313 ColorTransformMatrix* next = next_untyped->GetMatrix(); |
302 if (!next) | 314 if (!next) |
303 return false; | 315 return false; |
304 class Transform tmp = next->matrix_; | 316 class Transform tmp = next->matrix_; |
305 tmp *= matrix_; | 317 tmp *= matrix_; |
306 matrix_ = tmp; | 318 matrix_ = tmp; |
307 return true; | 319 return true; |
308 } | 320 } |
309 | 321 |
310 bool IsNull() override { | 322 bool IsNull() override { |
311 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); | 323 return SkMatrixIsApproximatelyIdentity(matrix_.matrix()); |
312 } | 324 } |
313 | 325 |
314 void Transform(ColorTransform::TriStim* colors, size_t num) override { | 326 void Transform(ColorTransform::TriStim* colors, size_t num) override { |
315 for (size_t i = 0; i < num; i++) | 327 for (size_t i = 0; i < num; i++) |
316 matrix_.TransformPoint(colors + i); | 328 matrix_.TransformPoint(colors + i); |
317 } | 329 } |
318 | 330 |
| 331 bool CanAppendShaderSource() override { return true; } |
| 332 |
| 333 void AppendShaderSource(std::string* result) override { |
| 334 const SkMatrix44& m = matrix_.matrix(); |
| 335 SRC("color = mat3(%f, %f, %f, %f, %f, %f, %f, %f, %f) * color;", |
| 336 m.get(0, 0), m.get(1, 0), m.get(2, 0), // column 1 |
| 337 m.get(0, 1), m.get(1, 1), m.get(2, 1), // column 2 |
| 338 m.get(0, 2), m.get(1, 2), m.get(2, 2)); // column 3 |
| 339 SRC("color += vec3(%f, %f, %f);", m.get(0, 3), m.get(1, 3), m.get(2, 3)); |
| 340 } |
| 341 |
319 private: | 342 private: |
320 class Transform matrix_; | 343 class Transform matrix_; |
321 }; | 344 }; |
322 | 345 |
323 class ColorTransformFromLinear : public ColorTransformStep { | 346 class ColorTransformFromLinear : public ColorTransformStep { |
324 public: | 347 public: |
325 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer, | 348 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer, |
326 const SkColorSpaceTransferFn& fn, | 349 const SkColorSpaceTransferFn& fn, |
327 bool fn_valid) | 350 bool fn_valid) |
328 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { | 351 : transfer_(transfer), fn_(fn), fn_valid_(fn_valid) { |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
584 | 607 |
585 // TODO(hubbe): shrink gamuts here (never stretch gamuts) | 608 // TODO(hubbe): shrink gamuts here (never stretch gamuts) |
586 } | 609 } |
587 | 610 |
588 steps_.push_back( | 611 steps_.push_back( |
589 base::MakeUnique<ColorTransformMatrix>(GetRangeAdjustMatrix(from))); | 612 base::MakeUnique<ColorTransformMatrix>(GetRangeAdjustMatrix(from))); |
590 | 613 |
591 steps_.push_back( | 614 steps_.push_back( |
592 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); | 615 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); |
593 | 616 |
| 617 // If the target color space is not defined, just apply the adjust and |
| 618 // tranfer matrices. |
| 619 if (!to.IsValid()) |
| 620 return; |
| 621 |
594 SkColorSpaceTransferFn to_linear_fn; | 622 SkColorSpaceTransferFn to_linear_fn; |
595 bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn); | 623 bool to_linear_fn_valid = from.GetTransferFunction(&to_linear_fn); |
596 steps_.push_back(base::MakeUnique<ColorTransformToLinear>( | 624 steps_.push_back(base::MakeUnique<ColorTransformToLinear>( |
597 from.transfer_, to_linear_fn, to_linear_fn_valid)); | 625 from.transfer_, to_linear_fn, to_linear_fn_valid)); |
598 | 626 |
599 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { | 627 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { |
600 // BT2020 CL is a special case. | 628 // BT2020 CL is a special case. |
601 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); | 629 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); |
602 } | 630 } |
603 steps_.push_back( | 631 steps_.push_back( |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 | 744 |
717 if (to_profile) { | 745 if (to_profile) { |
718 steps_.push_back(base::MakeUnique<QCMSColorTransform>( | 746 steps_.push_back(base::MakeUnique<QCMSColorTransform>( |
719 GetXYZD50Profile(), std::move(to_profile))); | 747 GetXYZD50Profile(), std::move(to_profile))); |
720 } | 748 } |
721 | 749 |
722 if (intent != Intent::TEST_NO_OPT) | 750 if (intent != Intent::TEST_NO_OPT) |
723 Simplify(); | 751 Simplify(); |
724 } | 752 } |
725 | 753 |
| 754 std::string ColorTransformInternal::GetShaderSource() const { |
| 755 std::string result; |
| 756 result += "vec3 DoColorConversion(vec3 color) {\n"; |
| 757 for (const auto& step : steps_) |
| 758 step->AppendShaderSource(&result); |
| 759 result += " return color;\n"; |
| 760 result += "}\n"; |
| 761 return result; |
| 762 } |
| 763 |
| 764 bool ColorTransformInternal::CanGetShaderSource() const { |
| 765 for (const auto& step : steps_) { |
| 766 if (!step->CanAppendShaderSource()) |
| 767 return false; |
| 768 } |
| 769 return true; |
| 770 } |
| 771 |
726 ColorTransformInternal::~ColorTransformInternal() {} | 772 ColorTransformInternal::~ColorTransformInternal() {} |
727 | 773 |
728 void ColorTransformInternal::Simplify() { | 774 void ColorTransformInternal::Simplify() { |
729 for (auto iter = steps_.begin(); iter != steps_.end();) { | 775 for (auto iter = steps_.begin(); iter != steps_.end();) { |
730 std::unique_ptr<ColorTransformStep>& this_step = *iter; | 776 std::unique_ptr<ColorTransformStep>& this_step = *iter; |
731 | 777 |
732 // Try to Join |next_step| into |this_step|. If successful, re-visit the | 778 // Try to Join |next_step| into |this_step|. If successful, re-visit the |
733 // step before |this_step|. | 779 // step before |this_step|. |
734 auto iter_next = iter; | 780 auto iter_next = iter; |
735 iter_next++; | 781 iter_next++; |
(...skipping 26 matching lines...) Expand all Loading... |
762 const ColorSpace& to, | 808 const ColorSpace& to, |
763 Intent intent) { | 809 Intent intent) { |
764 return std::unique_ptr<ColorTransform>( | 810 return std::unique_ptr<ColorTransform>( |
765 new ColorTransformInternal(from, to, intent)); | 811 new ColorTransformInternal(from, to, intent)); |
766 } | 812 } |
767 | 813 |
768 ColorTransform::ColorTransform() {} | 814 ColorTransform::ColorTransform() {} |
769 ColorTransform::~ColorTransform() {} | 815 ColorTransform::~ColorTransform() {} |
770 | 816 |
771 } // namespace gfx | 817 } // namespace gfx |
OLD | NEW |