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 "base/logging.h" | 5 #include "base/logging.h" |
6 #include "testing/gtest/include/gtest/gtest.h" | 6 #include "testing/gtest/include/gtest/gtest.h" |
7 #include "ui/gfx/color_space.h" | 7 #include "ui/gfx/color_space.h" |
8 #include "ui/gfx/color_transform.h" | 8 #include "ui/gfx/color_transform.h" |
9 #include "ui/gfx/icc_profile.h" | 9 #include "ui/gfx/icc_profile.h" |
10 #include "ui/gfx/test/icc_profiles.h" | 10 #include "ui/gfx/test/icc_profiles.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 EXPECT_NEAR(tmp.y(), 1.0f, 0.001f); | 75 EXPECT_NEAR(tmp.y(), 1.0f, 0.001f); |
76 EXPECT_NEAR(tmp.z(), 1.0f, 0.001f); | 76 EXPECT_NEAR(tmp.z(), 1.0f, 0.001f); |
77 | 77 |
78 // Test a blue color | 78 // Test a blue color |
79 tmp = ColorTransform::TriStim(128.0f / 255.0f, 240.0f / 255.0f, 0.5f); | 79 tmp = ColorTransform::TriStim(128.0f / 255.0f, 240.0f / 255.0f, 0.5f); |
80 t->Transform(&tmp, 1); | 80 t->Transform(&tmp, 1); |
81 EXPECT_GT(tmp.z(), tmp.x()); | 81 EXPECT_GT(tmp.z(), tmp.x()); |
82 EXPECT_GT(tmp.z(), tmp.y()); | 82 EXPECT_GT(tmp.z(), tmp.y()); |
83 } | 83 } |
84 | 84 |
| 85 TEST(SimpleColorSpace, TransferFnCancel) { |
| 86 ColorSpace::PrimaryID primary = ColorSpace::PrimaryID::BT709; |
| 87 ColorSpace::MatrixID matrix = ColorSpace::MatrixID::RGB; |
| 88 ColorSpace::RangeID range = ColorSpace::RangeID::FULL; |
| 89 |
| 90 // BT709 has a gamma of 2.2222 (with some adjustments) |
| 91 ColorSpace bt709(primary, ColorSpace::TransferID::BT709, matrix, range); |
| 92 |
| 93 // IEC61966_2_1 has the sRGB gamma of 2.4 (with some adjustments) |
| 94 ColorSpace srgb(primary, ColorSpace::TransferID::IEC61966_2_1, matrix, range); |
| 95 |
| 96 // gamma28 is a simple exponential |
| 97 ColorSpace gamma28(primary, ColorSpace::TransferID::GAMMA28, matrix, range); |
| 98 |
| 99 // gamma24 is a simple exponential |
| 100 ColorSpace gamma24(primary, ColorSpace::TransferID::GAMMA24, matrix, range); |
| 101 |
| 102 // BT709 source is common for video and sRGB destination is common for |
| 103 // monitors. The two transfer functions are very close, and should cancel |
| 104 // out (so the transfer between them should be the identity). This particular |
| 105 // case is important for power reasons. |
| 106 std::unique_ptr<ColorTransform> bt709_to_srgb( |
| 107 ColorTransform::NewColorTransform( |
| 108 bt709, srgb, ColorTransform::Intent::INTENT_PERCEPTUAL)); |
| 109 EXPECT_EQ(bt709_to_srgb->NumberOfStepsForTesting(), 0u); |
| 110 |
| 111 // Gamma 2.8 isn't even close to BT709 and won't cancel out (so we will have |
| 112 // two steps in the transform -- to-linear and from-linear). |
| 113 std::unique_ptr<ColorTransform> bt709_to_gamma28( |
| 114 ColorTransform::NewColorTransform( |
| 115 bt709, gamma28, ColorTransform::Intent::INTENT_PERCEPTUAL)); |
| 116 EXPECT_EQ(bt709_to_gamma28->NumberOfStepsForTesting(), 2u); |
| 117 |
| 118 // Gamma 2.4 is closer to BT709, but not close enough to actually cancel out. |
| 119 std::unique_ptr<ColorTransform> bt709_to_gamma24( |
| 120 ColorTransform::NewColorTransform( |
| 121 bt709, gamma24, ColorTransform::Intent::INTENT_PERCEPTUAL)); |
| 122 EXPECT_EQ(bt709_to_gamma24->NumberOfStepsForTesting(), 2u); |
| 123 } |
| 124 |
85 TEST(SimpleColorSpace, SRGBFromICCAndNotICC) { | 125 TEST(SimpleColorSpace, SRGBFromICCAndNotICC) { |
86 float kEpsilon = 0.001f; | 126 float kEpsilon = 0.001f; |
87 ColorTransform::TriStim value_fromicc; | 127 ColorTransform::TriStim value_fromicc; |
88 ColorTransform::TriStim value_default; | 128 ColorTransform::TriStim value_default; |
89 | 129 |
90 ICCProfile srgb_icc_profile = ICCProfileForTestingSRGB(); | 130 ICCProfile srgb_icc_profile = ICCProfileForTestingSRGB(); |
91 ColorSpace srgb_fromicc = srgb_icc_profile.GetColorSpace(); | 131 ColorSpace srgb_fromicc = srgb_icc_profile.GetColorSpace(); |
92 ColorSpace srgb_default = gfx::ColorSpace::CreateSRGB(); | 132 ColorSpace srgb_default = gfx::ColorSpace::CreateSRGB(); |
93 ColorSpace xyzd50 = gfx::ColorSpace::CreateXYZD50(); | 133 ColorSpace xyzd50 = gfx::ColorSpace::CreateXYZD50(); |
94 | 134 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 std::unique_ptr<ColorTransform> t1(ColorTransform::NewColorTransform( | 265 std::unique_ptr<ColorTransform> t1(ColorTransform::NewColorTransform( |
226 unknown, ColorSpace::CreateSRGB(), | 266 unknown, ColorSpace::CreateSRGB(), |
227 ColorTransform::Intent::INTENT_PERCEPTUAL)); | 267 ColorTransform::Intent::INTENT_PERCEPTUAL)); |
228 EXPECT_EQ(t1->NumberOfStepsForTesting(), 0u); | 268 EXPECT_EQ(t1->NumberOfStepsForTesting(), 0u); |
229 std::unique_ptr<ColorTransform> t2(ColorTransform::NewColorTransform( | 269 std::unique_ptr<ColorTransform> t2(ColorTransform::NewColorTransform( |
230 unknown, ColorSpace::CreateXYZD50(), | 270 unknown, ColorSpace::CreateXYZD50(), |
231 ColorTransform::Intent::INTENT_PERCEPTUAL)); | 271 ColorTransform::Intent::INTENT_PERCEPTUAL)); |
232 EXPECT_EQ(t2->NumberOfStepsForTesting(), 0u); | 272 EXPECT_EQ(t2->NumberOfStepsForTesting(), 0u); |
233 } | 273 } |
234 | 274 |
| 275 // This tests to make sure that we don't emit the "if" or "pow" parts of a |
| 276 // transfer function unless necessary. |
| 277 TEST(SimpleColorSpace, ShaderSourceTrFnOptimizations) { |
| 278 SkMatrix44 primaries; |
| 279 gfx::ColorSpace::CreateSRGB().GetPrimaryMatrix(&primaries); |
| 280 |
| 281 SkColorSpaceTransferFn fn_no_pow_no_if = { |
| 282 1.f, 2.f, 0.f, 1.f, 0.f, 0.f, 0.f, |
| 283 }; |
| 284 SkColorSpaceTransferFn fn_no_pow_yes_if = { |
| 285 1.f, 2.f, 0.f, 1.f, 0.5f, 0.f, 0.f, |
| 286 }; |
| 287 SkColorSpaceTransferFn fn_yes_pow_no_if = { |
| 288 2.f, 2.f, 0.f, 1.f, 0.f, 0.f, 0.f, |
| 289 }; |
| 290 SkColorSpaceTransferFn fn_yes_pow_yes_if = { |
| 291 2.f, 2.f, 0.f, 1.f, 0.5f, 0.f, 0.f, |
| 292 }; |
| 293 |
| 294 gfx::ColorSpace src; |
| 295 gfx::ColorSpace dst = gfx::ColorSpace::CreateXYZD50(); |
| 296 std::string shader_string; |
| 297 |
| 298 src = gfx::ColorSpace::CreateCustom(primaries, fn_no_pow_no_if); |
| 299 shader_string = ColorTransform::NewColorTransform( |
| 300 src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL) |
| 301 ->GetShaderSource(); |
| 302 EXPECT_EQ(shader_string.find("if ("), std::string::npos); |
| 303 EXPECT_EQ(shader_string.find("pow("), std::string::npos); |
| 304 |
| 305 src = gfx::ColorSpace::CreateCustom(primaries, fn_no_pow_yes_if); |
| 306 shader_string = ColorTransform::NewColorTransform( |
| 307 src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL) |
| 308 ->GetShaderSource(); |
| 309 EXPECT_NE(shader_string.find("if ("), std::string::npos); |
| 310 EXPECT_EQ(shader_string.find("pow("), std::string::npos); |
| 311 |
| 312 src = gfx::ColorSpace::CreateCustom(primaries, fn_yes_pow_no_if); |
| 313 shader_string = ColorTransform::NewColorTransform( |
| 314 src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL) |
| 315 ->GetShaderSource(); |
| 316 EXPECT_EQ(shader_string.find("if ("), std::string::npos); |
| 317 EXPECT_NE(shader_string.find("pow("), std::string::npos); |
| 318 |
| 319 src = gfx::ColorSpace::CreateCustom(primaries, fn_yes_pow_yes_if); |
| 320 shader_string = ColorTransform::NewColorTransform( |
| 321 src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL) |
| 322 ->GetShaderSource(); |
| 323 EXPECT_NE(shader_string.find("if ("), std::string::npos); |
| 324 EXPECT_NE(shader_string.find("pow("), std::string::npos); |
| 325 } |
| 326 |
| 327 // Note: This is not actually "testing" anything -- the goal of this test is to |
| 328 // to make reviewing shader code simpler by giving an example of the resulting |
| 329 // shader source. This should be updated whenever shader generation is updated. |
| 330 // This test produces slightly different results on Android. |
| 331 #if defined(OS_ANDROID) |
| 332 #define MAYBE_SampleShaderSource DISABLED_SampleShaderSource |
| 333 #else |
| 334 #define MAYBE_SampleShaderSource SampleShaderSource |
| 335 #endif |
| 336 TEST(SimpleColorSpace, MAYBE_SampleShaderSource) { |
| 337 ColorSpace bt709 = ColorSpace::CreateREC709(); |
| 338 ColorSpace output(ColorSpace::PrimaryID::BT2020, |
| 339 ColorSpace::TransferID::GAMMA28); |
| 340 std::string source = |
| 341 ColorTransform::NewColorTransform( |
| 342 bt709, output, ColorTransform::Intent::INTENT_PERCEPTUAL) |
| 343 ->GetShaderSource(); |
| 344 std::string expected = |
| 345 "vec3 DoColorConversion(vec3 color) {\n" |
| 346 " color = mat3(+1.16438353e+00, +1.16438353e+00, +1.16438353e+00,\n" |
| 347 " -2.28029018e-09, -2.13248596e-01, +2.11240172e+00,\n" |
| 348 " +1.79274118e+00, -5.32909274e-01, -5.96049432e-10)" |
| 349 " * color;\n" |
| 350 " color = vec3(-9.69429970e-01, +3.00019622e-01, -1.12926030e+00)" |
| 351 " + color;\n" |
| 352 " if (color.r < 0.040450)\n" |
| 353 " color.r = +7.73993805e-02 * color.r;\n" |
| 354 " else\n" |
| 355 " color.r = pow(+9.47867334e-01 * color.r + +5.21326549e-02, " |
| 356 "+2.40000010e+00);\n" |
| 357 " if (color.g < 0.040450)\n" |
| 358 " color.g = +7.73993805e-02 * color.g;\n" |
| 359 " else\n" |
| 360 " color.g = pow(+9.47867334e-01 * color.g + +5.21326549e-02, " |
| 361 "+2.40000010e+00);\n" |
| 362 " if (color.b < 0.040450)\n" |
| 363 " color.b = +7.73993805e-02 * color.b;\n" |
| 364 " else\n" |
| 365 " color.b = pow(+9.47867334e-01 * color.b + +5.21326549e-02, " |
| 366 "+2.40000010e+00);\n" |
| 367 " color = mat3(+6.27403915e-01, +6.90973178e-02, +1.63914412e-02,\n" |
| 368 " +3.29283148e-01, +9.19540286e-01, +8.80132914e-02,\n" |
| 369 " +4.33131084e-02, +1.13623003e-02, +8.95595253e-01) " |
| 370 "* color;\n" |
| 371 " color = vec3(+0.00000000e+00, +0.00000000e+00, +0.00000000e+00) " |
| 372 "+ color;\n" |
| 373 " color.r = pow(color.r, +3.57142866e-01);\n" |
| 374 " color.g = pow(color.g, +3.57142866e-01);\n" |
| 375 " color.b = pow(color.b, +3.57142866e-01);\n" |
| 376 " return color;\n" |
| 377 "}\n"; |
| 378 EXPECT_EQ(source, expected); |
| 379 } |
| 380 |
235 class TransferTest : public testing::TestWithParam<ColorSpace::TransferID> {}; | 381 class TransferTest : public testing::TestWithParam<ColorSpace::TransferID> {}; |
236 | 382 |
237 TEST_P(TransferTest, basicTest) { | 383 TEST_P(TransferTest, basicTest) { |
238 gfx::ColorSpace space_with_transfer(ColorSpace::PrimaryID::BT709, GetParam(), | 384 gfx::ColorSpace space_with_transfer(ColorSpace::PrimaryID::BT709, GetParam(), |
239 ColorSpace::MatrixID::RGB, | 385 ColorSpace::MatrixID::RGB, |
240 ColorSpace::RangeID::FULL); | 386 ColorSpace::RangeID::FULL); |
241 gfx::ColorSpace space_linear( | 387 gfx::ColorSpace space_linear( |
242 ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::LINEAR, | 388 ColorSpace::PrimaryID::BT709, ColorSpace::TransferID::LINEAR, |
243 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL); | 389 ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL); |
244 | 390 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 | 479 |
334 INSTANTIATE_TEST_CASE_P( | 480 INSTANTIATE_TEST_CASE_P( |
335 C, | 481 C, |
336 ColorSpaceTest, | 482 ColorSpaceTest, |
337 testing::Combine(testing::ValuesIn(all_primaries), | 483 testing::Combine(testing::ValuesIn(all_primaries), |
338 testing::Values(ColorSpace::TransferID::BT709), | 484 testing::Values(ColorSpace::TransferID::BT709), |
339 testing::ValuesIn(all_matrices), | 485 testing::ValuesIn(all_matrices), |
340 testing::ValuesIn(all_ranges), | 486 testing::ValuesIn(all_ranges), |
341 testing::ValuesIn(intents))); | 487 testing::ValuesIn(intents))); |
342 } // namespace | 488 } // namespace |
OLD | NEW |