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

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

Issue 2728173004: HDR: Do nonlinear blending in the compositor (Closed)
Patch Set: Roll in sRGB-extended 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
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>
11 #include <sstream> 11 #include <sstream>
12 12
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "third_party/qcms/src/qcms.h" 16 #include "third_party/qcms/src/qcms.h"
17 #include "ui/gfx/color_space.h" 17 #include "ui/gfx/color_space.h"
18 #include "ui/gfx/icc_profile.h" 18 #include "ui/gfx/icc_profile.h"
19 #include "ui/gfx/skia_color_space_util.h" 19 #include "ui/gfx/skia_color_space_util.h"
20 #include "ui/gfx/transform.h" 20 #include "ui/gfx/transform.h"
21 21
22 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H 22 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H
23 extern "C" { 23 extern "C" {
24 #include "third_party/qcms/src/chain.h" 24 #include "third_party/qcms/src/chain.h"
25 }; 25 };
26 #endif 26 #endif
27 27
28 using std::abs;
29 using std::copysign;
28 using std::exp; 30 using std::exp;
29 using std::log; 31 using std::log;
30 using std::max; 32 using std::max;
31 using std::min; 33 using std::min;
32 using std::pow; 34 using std::pow;
33 using std::sqrt; 35 using std::sqrt;
34 36
35 namespace gfx { 37 namespace gfx {
36 38
37 namespace { 39 namespace {
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 *result << ");" << std::endl; 366 *result << ");" << std::endl;
365 } 367 }
366 } 368 }
367 369
368 private: 370 private:
369 class Transform matrix_; 371 class Transform matrix_;
370 }; 372 };
371 373
372 class ColorTransformSkTransferFn : public ColorTransformStep { 374 class ColorTransformSkTransferFn : public ColorTransformStep {
373 public: 375 public:
374 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn) 376 explicit ColorTransformSkTransferFn(const SkColorSpaceTransferFn& fn,
375 : fn_(fn) {} 377 bool extended)
378 : fn_(fn), extended_(extended) {}
376 ColorTransformSkTransferFn* GetSkTransferFn() override { return this; } 379 ColorTransformSkTransferFn* GetSkTransferFn() override { return this; }
377 380
378 bool Join(ColorTransformStep* next_untyped) override { 381 bool Join(ColorTransformStep* next_untyped) override {
379 ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn(); 382 ColorTransformSkTransferFn* next = next_untyped->GetSkTransferFn();
380 if (!next) 383 if (!next)
381 return false; 384 return false;
382 if (SkTransferFnsApproximatelyCancel(fn_, next->fn_)) { 385 if (!extended_ && !next->extended_ &&
386 SkTransferFnsApproximatelyCancel(fn_, next->fn_)) {
383 // Set to be the identity. 387 // Set to be the identity.
384 fn_.fA = 1; 388 fn_.fA = 1;
385 fn_.fB = 0; 389 fn_.fB = 0;
386 fn_.fC = 1; 390 fn_.fC = 1;
387 fn_.fD = 0; 391 fn_.fD = 0;
388 fn_.fE = 0; 392 fn_.fE = 0;
389 fn_.fF = 0; 393 fn_.fF = 0;
390 fn_.fG = 1; 394 fn_.fG = 1;
391 return true; 395 return true;
392 } 396 }
393 return false; 397 return false;
394 } 398 }
395 399
396 bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); } 400 bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); }
397 401
398 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 402 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
399 for (size_t i = 0; i < num; i++) { 403 for (size_t i = 0; i < num; i++) {
400 colors[i].set_x(SkTransferFnEval(fn_, colors[i].x())); 404 ColorTransform::TriStim& c = colors[i];
401 colors[i].set_y(SkTransferFnEval(fn_, colors[i].y())); 405 if (extended_) {
402 colors[i].set_z(SkTransferFnEval(fn_, colors[i].z())); 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 }
403 } 414 }
404 } 415 }
405 416
406 bool CanAppendShaderSource() override { return true; } 417 bool CanAppendShaderSource() override { return true; }
407 418
408 void AppendShaderSourceChannel(std::stringstream* result, const char* value) { 419 void AppendShaderSourceChannel(std::stringstream* result,
420 const std::string& value) {
421 std::string abs_value = "abs(" + value + ")";
409 const float kEpsilon = 1.f / 1024.f; 422 const float kEpsilon = 1.f / 1024.f;
410 423
411 // Construct the linear segment 424 // Construct the linear segment
412 // linear = C * x + F 425 // linear = C * x + F
413 // Elide operations that will be close to the identity. 426 // Elide operations that will be close to the identity.
414 std::string linear = value; 427 std::string linear = value;
415 if (std::abs(fn_.fC - 1.f) > kEpsilon) 428 if (std::abs(fn_.fC - 1.f) > kEpsilon)
416 linear = Str(fn_.fC) + " * " + linear; 429 linear = Str(fn_.fC) + " * " + linear;
417 if (std::abs(fn_.fF) > kEpsilon) 430 if (std::abs(fn_.fF) > kEpsilon)
418 linear = linear + " + " + Str(fn_.fF); 431 linear = linear + " + " + Str(fn_.fF);
419 432
420 // Construct the nonlinear segment. 433 // Construct the nonlinear segment.
421 // nonlinear = pow(A * x + B, G) + E 434 // nonlinear = pow(A * x + B, G) + E
422 // Elide operations (especially the pow) that will be close to the 435 // Elide operations (especially the pow) that will be close to the
423 // identity. 436 // identity.
424 std::string nonlinear = value; 437 std::string nonlinear = extended_ ? abs_value : value;
425 if (std::abs(fn_.fA - 1.f) > kEpsilon) 438 if (std::abs(fn_.fA - 1.f) > kEpsilon)
426 nonlinear = Str(fn_.fA) + " * " + nonlinear; 439 nonlinear = Str(fn_.fA) + " * " + nonlinear;
427 if (std::abs(fn_.fB) > kEpsilon) 440 if (std::abs(fn_.fB) > kEpsilon)
428 nonlinear = nonlinear + " + " + Str(fn_.fB); 441 nonlinear = nonlinear + " + " + Str(fn_.fB);
429 if (std::abs(fn_.fG - 1.f) > kEpsilon) 442 if (std::abs(fn_.fG - 1.f) > kEpsilon)
430 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")"; 443 nonlinear = "pow(" + nonlinear + ", " + Str(fn_.fG) + ")";
431 if (std::abs(fn_.fE) > kEpsilon) 444 if (std::abs(fn_.fE) > kEpsilon)
432 nonlinear = nonlinear + " + " + Str(fn_.fE); 445 nonlinear = nonlinear + " + " + Str(fn_.fE);
446 if (extended_) {
447 if (nonlinear == abs_value)
448 nonlinear = value;
449 else
450 nonlinear = "sign(" + value + ") * (" + nonlinear + ")";
451 }
433 452
434 // Add both parts, skpping the if clause if possible. 453 // Add both parts, skpping the if clause if possible.
435 if (fn_.fD > kEpsilon) { 454 if (fn_.fD > kEpsilon) {
436 *result << " if (" << value << " < " << Str(fn_.fD) << ")" << std::endl; 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 }
437 *result << " " << value << " = " << linear << ";" << std::endl; 462 *result << " " << value << " = " << linear << ";" << std::endl;
438 *result << " else" << std::endl; 463 *result << " else" << std::endl;
439 *result << " " << value << " = " << nonlinear << ";" << std::endl; 464 *result << " " << value << " = " << nonlinear << ";" << std::endl;
440 } else { 465 } else {
441 *result << " " << value << " = " << nonlinear << ";" << std::endl; 466 *result << " " << value << " = " << nonlinear << ";" << std::endl;
442 } 467 }
443 } 468 }
444 469
445 void AppendShaderSource(std::stringstream* result) override { 470 void AppendShaderSource(std::stringstream* result) override {
446 // Append the transfer function for each channel. 471 // Append the transfer function for each channel.
447 AppendShaderSourceChannel(result, "color.r"); 472 AppendShaderSourceChannel(result, "color.r");
448 AppendShaderSourceChannel(result, "color.g"); 473 AppendShaderSourceChannel(result, "color.g");
449 AppendShaderSourceChannel(result, "color.b"); 474 AppendShaderSourceChannel(result, "color.b");
450 } 475 }
451 476
452 private: 477 private:
453 SkColorSpaceTransferFn fn_; 478 SkColorSpaceTransferFn fn_;
479 // True if the transfer function is extended to be defined for all real
480 // values.
481 const bool extended_ = false;
454 }; 482 };
455 483
456 class ColorTransformFromLinear : public ColorTransformStep { 484 class ColorTransformFromLinear : public ColorTransformStep {
457 public: 485 public:
458 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer) 486 explicit ColorTransformFromLinear(ColorSpace::TransferID transfer)
459 : transfer_(transfer) {} 487 : transfer_(transfer) {}
460 ColorTransformFromLinear* GetFromLinear() override { return this; } 488 ColorTransformFromLinear* GetFromLinear() override { return this; }
461 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } 489 bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; }
462 void Transform(ColorTransform::TriStim* colors, size_t num) const override { 490 void Transform(ColorTransform::TriStim* colors, size_t num) const override {
463 for (size_t i = 0; i < num; i++) { 491 for (size_t i = 0; i < num; i++) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from)))); 704 base::MakeUnique<ColorTransformMatrix>(Invert(GetTransferMatrix(from))));
677 705
678 // If the target color space is not defined, just apply the adjust and 706 // If the target color space is not defined, just apply the adjust and
679 // tranfer matrices. This path is used by YUV to RGB color conversion 707 // tranfer matrices. This path is used by YUV to RGB color conversion
680 // when full color conversion is not enabled. 708 // when full color conversion is not enabled.
681 if (!to.IsValid()) 709 if (!to.IsValid())
682 return; 710 return;
683 711
684 SkColorSpaceTransferFn to_linear_fn; 712 SkColorSpaceTransferFn to_linear_fn;
685 if (from.GetTransferFunction(&to_linear_fn)) { 713 if (from.GetTransferFunction(&to_linear_fn)) {
686 steps_.push_back( 714 steps_.push_back(base::MakeUnique<ColorTransformSkTransferFn>(
687 base::MakeUnique<ColorTransformSkTransferFn>(to_linear_fn)); 715 to_linear_fn, from.HasExtendedSkTransferFn()));
688 } else { 716 } else {
689 steps_.push_back(base::MakeUnique<ColorTransformToLinear>(from.transfer_)); 717 steps_.push_back(base::MakeUnique<ColorTransformToLinear>(from.transfer_));
690 } 718 }
691 719
692 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) { 720 if (from.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
693 // BT2020 CL is a special case. 721 // BT2020 CL is a special case.
694 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>()); 722 steps_.push_back(base::MakeUnique<ColorTransformFromBT2020CL>());
695 } 723 }
696 steps_.push_back( 724 steps_.push_back(
697 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from))); 725 base::MakeUnique<ColorTransformMatrix>(GetPrimaryTransform(from)));
698 726
699 steps_.push_back( 727 steps_.push_back(
700 base::MakeUnique<ColorTransformMatrix>(Invert(GetPrimaryTransform(to)))); 728 base::MakeUnique<ColorTransformMatrix>(Invert(GetPrimaryTransform(to))));
701 if (to.matrix_ == ColorSpace::MatrixID::BT2020_CL) { 729 if (to.matrix_ == ColorSpace::MatrixID::BT2020_CL) {
702 // BT2020 CL is a special case. 730 // BT2020 CL is a special case.
703 steps_.push_back(base::MakeUnique<ColorTransformToBT2020CL>()); 731 steps_.push_back(base::MakeUnique<ColorTransformToBT2020CL>());
704 } 732 }
705 733
706 SkColorSpaceTransferFn from_linear_fn; 734 SkColorSpaceTransferFn from_linear_fn;
707 if (to.GetInverseTransferFunction(&from_linear_fn)) { 735 if (to.GetInverseTransferFunction(&from_linear_fn)) {
708 steps_.push_back( 736 steps_.push_back(base::MakeUnique<ColorTransformSkTransferFn>(
709 base::MakeUnique<ColorTransformSkTransferFn>(from_linear_fn)); 737 from_linear_fn, to.HasExtendedSkTransferFn()));
710 } else { 738 } else {
711 steps_.push_back(base::MakeUnique<ColorTransformFromLinear>(to.transfer_)); 739 steps_.push_back(base::MakeUnique<ColorTransformFromLinear>(to.transfer_));
712 } 740 }
713 741
714 steps_.push_back( 742 steps_.push_back(
715 base::MakeUnique<ColorTransformMatrix>(GetTransferMatrix(to))); 743 base::MakeUnique<ColorTransformMatrix>(GetTransferMatrix(to)));
716 744
717 steps_.push_back( 745 steps_.push_back(
718 base::MakeUnique<ColorTransformMatrix>(Invert(GetRangeAdjustMatrix(to)))); 746 base::MakeUnique<ColorTransformMatrix>(Invert(GetRangeAdjustMatrix(to))));
719 } 747 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
885 const ColorSpace& to, 913 const ColorSpace& to,
886 Intent intent) { 914 Intent intent) {
887 return std::unique_ptr<ColorTransform>( 915 return std::unique_ptr<ColorTransform>(
888 new ColorTransformInternal(from, to, intent)); 916 new ColorTransformInternal(from, to, intent));
889 } 917 }
890 918
891 ColorTransform::ColorTransform() {} 919 ColorTransform::ColorTransform() {}
892 ColorTransform::~ColorTransform() {} 920 ColorTransform::~ColorTransform() {}
893 921
894 } // namespace gfx 922 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698