| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/display/util/display_util.h" |
| |
| #include <vector> |
| |
| #include "base/test/metrics/histogram_tester.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/display/test/display_test_util.h" |
| #include "ui/display/util/edid_parser.h" |
| #include "ui/gfx/color_space.h" |
| |
| namespace display { |
| |
| namespace { |
| |
| // HP z32x monitor. |
| constexpr uint8_t kHPz32x[] = { |
| 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x22, 0xF0, 0x75, 0x32, |
| 0x01, 0x01, 0x01, 0x01, 0x1B, 0x1B, 0x01, 0x04, 0xB5, 0x46, 0x27, 0x78, |
| 0x3A, 0x8D, 0x15, 0xAC, 0x51, 0x32, 0xB8, 0x26, 0x0B, 0x50, 0x54, 0x21, |
| 0x08, 0x00, 0xD1, 0xC0, 0xA9, 0xC0, 0x81, 0xC0, 0xD1, 0x00, 0xB3, 0x00, |
| 0x95, 0x00, 0xA9, 0x40, 0x81, 0x80, 0x4D, 0xD0, 0x00, 0xA0, 0xF0, 0x70, |
| 0x3E, 0x80, 0x30, 0x20, 0x35, 0x00, 0xB9, 0x88, 0x21, 0x00, 0x00, 0x1A, |
| 0x00, 0x00, 0x00, 0xFD, 0x00, 0x18, 0x3C, 0x1E, 0x87, 0x3C, 0x00, 0x0A, |
| 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x48, |
| 0x50, 0x20, 0x5A, 0x33, 0x32, 0x78, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 0x00, 0x00, 0x00, 0xFF, 0x00, 0x43, 0x4E, 0x43, 0x37, 0x32, 0x37, 0x30, |
| 0x4D, 0x57, 0x30, 0x0A, 0x20, 0x20, 0x01, 0x46, 0x02, 0x03, 0x18, 0xF1, |
| 0x4B, 0x10, 0x1F, 0x04, 0x13, 0x03, 0x12, 0x02, 0x11, 0x01, 0x05, 0x14, |
| 0x23, 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0xA3, 0x66, 0x00, 0xA0, |
| 0xF0, 0x70, 0x1F, 0x80, 0x30, 0x20, 0x35, 0x00, 0xB9, 0x88, 0x21, 0x00, |
| 0x00, 0x1A, 0x56, 0x5E, 0x00, 0xA0, 0xA0, 0xA0, 0x29, 0x50, 0x30, 0x20, |
| 0x35, 0x00, 0xB9, 0x88, 0x21, 0x00, 0x00, 0x1A, 0xEF, 0x51, 0x00, 0xA0, |
| 0xF0, 0x70, 0x19, 0x80, 0x30, 0x20, 0x35, 0x00, 0xB9, 0x88, 0x21, 0x00, |
| 0x00, 0x1A, 0xE2, 0x68, 0x00, 0xA0, 0xA0, 0x40, 0x2E, 0x60, 0x20, 0x30, |
| 0x63, 0x00, 0xB9, 0x88, 0x21, 0x00, 0x00, 0x1C, 0x28, 0x3C, 0x80, 0xA0, |
| 0x70, 0xB0, 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0xB9, 0x88, 0x21, 0x00, |
| 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x3E}; |
| |
| // Chromebook Samus internal display. |
| constexpr uint8_t kSamus[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0xe4, 0x2e, 0x04, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0x04, 0xa5, 0x1b, 0x12, 0x96, |
| 0x02, 0x4f, 0xd5, 0xa2, 0x59, 0x52, 0x93, 0x26, 0x17, 0x50, 0x54, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x6d, 0x6f, 0x00, 0x9e, 0xa0, 0xa4, |
| 0x31, 0x60, 0x30, 0x20, 0x3a, 0x00, 0x10, 0xb5, 0x10, 0x00, 0x00, 0x19, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x4c, |
| 0x47, 0x20, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x0a, 0x20, 0x20, |
| 0x00, 0x00, 0x00, 0xfe, 0x00, 0x4c, 0x50, 0x31, 0x32, 0x39, 0x51, 0x45, |
| 0x32, 0x2d, 0x53, 0x50, 0x41, 0x31, 0x00, 0x6c}; |
| |
| // Chromebook Eve internal display. |
| constexpr uint8_t kEve[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4d, 0x10, 0x8a, 0x14, |
| 0x00, 0x00, 0x00, 0x00, 0x16, 0x1b, 0x01, 0x04, 0xa5, 0x1a, 0x11, 0x78, |
| 0x06, 0xde, 0x50, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xbb, 0x62, 0x60, 0xa0, 0x90, 0x40, |
| 0x2e, 0x60, 0x30, 0x20, 0x3a, 0x00, 0x03, 0xad, 0x10, 0x00, 0x00, 0x18, |
| 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xfc, 0x00, 0x4c, 0x51, 0x31, 0x32, 0x33, 0x50, 0x31, |
| 0x4a, 0x58, 0x33, 0x32, 0x0a, 0x20, 0x00, 0xb6}; |
| |
| // Invalid EDID: too short to contain chromaticity nor gamma information. |
| constexpr uint8_t kInvalidEdid[] = { |
| 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x22, 0xF0, 0x76, 0x26, |
| 0x01, 0x01, 0x01, 0x01, 0x02, 0x12, 0x01, 0x03, 0x80, 0x34, 0x21}; |
| |
| // Partially valid EDID: gamma information is marked as non existent. |
| constexpr uint8_t kEdidWithNoGamma[] = { |
| 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x22, 0xF0, 0x76, 0x26, |
| 0x01, 0x01, 0x01, 0x01, 0x02, 0x12, 0x01, 0x03, 0x80, 0x34, 0x21, 0xFF, |
| 0xEE, 0xEF, 0x95, 0xA3, 0x54, 0x4C, 0x9B, 0x26, 0x0F, 0x50, 0x54, 0xA5, |
| 0x6B, 0x80, 0x81, 0x40, 0x81, 0x80, 0x81, 0x99, 0x71, 0x00, 0xA9, 0x00}; |
| |
| // Screebo display with chromaticities near P3 |
| constexpr uint8_t kScreeboP3[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x09, 0xe5, 0x1b, 0x0c, |
| 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x01, 0x04, 0xb5, 0x1e, 0x13, 0x78, |
| 0x03, 0x14, 0xd5, 0xae, 0x51, 0x42, 0xb2, 0x24, 0x0f, 0x50, 0x54, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xc0, 0xd8, 0x00, 0xa0, 0xa0, 0x40, |
| 0x64, 0x60, 0x30, 0x20, 0x36, 0x00, 0x2e, 0xbc, 0x10, 0x00, 0x00, 0x1a, |
| 0x60, 0x6c, 0x00, 0xa0, 0xa0, 0x40, 0x64, 0x60, 0x30, 0x20, 0x36, 0x00, |
| 0x2e, 0xbc, 0x10, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x30, |
| 0x78, 0xcc, 0xcc, 0x37, 0x01, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 0x00, 0x00, 0x00, 0xfe, 0x00, 0x4e, 0x45, 0x31, 0x34, 0x30, 0x51, 0x44, |
| 0x4d, 0x2d, 0x4e, 0x58, 0x35, 0x0a, 0x01, 0x1b, 0x02, 0x03, 0x22, 0x00, |
| 0xe3, 0x05, 0x80, 0x00, 0xe6, 0x06, 0x05, 0x01, 0x6a, 0x6a, 0x43, 0x72, |
| 0x1a, 0x00, 0x00, 0x03, 0x03, 0x30, 0x78, 0x00, 0x20, 0x6a, 0x43, 0x6a, |
| 0x43, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x3c}; |
| |
| // EDID with only DCI-P3 in colorimetry data block |
| constexpr uint8_t kCDBP3[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x06, 0xb3, 0xda, 0x16, |
| 0x5e, 0x42, 0x02, 0x00, 0x15, 0x20, 0x01, 0x04, 0xb5, 0x22, 0x13, 0x78, |
| 0x3a, 0x0c, 0xf5, 0xae, 0x52, 0x3c, 0xb9, 0x23, 0x0c, 0x50, 0x54, 0x21, |
| 0x08, 0x00, 0xb3, 0x00, 0x95, 0x00, 0x81, 0x80, 0x81, 0x40, 0x81, 0xc0, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x35, 0x36, 0x80, 0xa0, 0x70, 0x38, |
| 0x20, 0x40, 0x30, 0x20, 0x88, 0x00, 0x58, 0xc2, 0x10, 0x00, 0x00, 0x1b, |
| 0x00, 0x00, 0x00, 0xff, 0x00, 0x4e, 0x35, 0x4c, 0x4d, 0x54, 0x46, 0x31, |
| 0x34, 0x38, 0x30, 0x36, 0x32, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, |
| 0x3d, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, |
| 0x00, 0x00, 0x00, 0xfc, 0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x4d, 0x51, |
| 0x31, 0x36, 0x41, 0x48, 0x0a, 0x20, 0x01, 0x55, |
| |
| 0x02, 0x03, 0x30, 0xf1, 0x52, 0x01, 0x03, 0x02, 0x04, 0x0e, 0x0f, 0x90, |
| 0x12, 0x11, 0x13, 0x1e, 0x1d, 0x1f, 0x05, 0x14, 0x20, 0x21, 0x22, 0x23, |
| 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00, 0x20, |
| 0x00, 0xe3, 0x05, 0x00, 0x81, 0xe6, 0x06, 0x05, 0x01, 0x5c, 0x5c, 0x09, |
| 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, |
| 0x58, 0xc2, 0x10, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a}; |
| |
| // Chromebook Samsung Galaxy (kohaku) that supports HDR metadata. |
| constexpr uint8_t kHDR[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x83, 0x42, 0x41, |
| 0x00, 0x00, 0x00, 0x00, 0x13, 0x1d, 0x01, 0x04, 0xb5, 0x1d, 0x11, 0x78, |
| 0x02, 0x38, 0xd1, 0xae, 0x51, 0x3b, 0xb8, 0x23, 0x0b, 0x50, 0x54, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xb9, 0xd5, 0x00, 0x40, 0xf1, 0x70, |
| 0x20, 0x80, 0x30, 0x20, 0x88, 0x00, 0x26, 0xa5, 0x10, 0x00, 0x00, 0x1b, |
| 0xb9, 0xd5, 0x00, 0x40, 0xf1, 0x70, 0x20, 0x80, 0x30, 0x20, 0x88, 0x00, |
| 0x26, 0xa5, 0x10, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xff, |
| 0x09, 0x3c, 0xff, 0x09, 0x3c, 0x2c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xfe, 0x00, 0x41, 0x54, 0x4e, 0x41, 0x33, 0x33, 0x54, |
| 0x50, 0x30, 0x34, 0x2d, 0x30, 0x20, 0x01, 0xba, 0x02, 0x03, 0x0f, 0x00, |
| 0xe3, 0x05, 0x80, 0x00, 0xe6, 0x06, 0x05, 0x01, 0x73, 0x6d, 0x07, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0xab}; |
| |
| // EDID collected in the wild: valid but with primaries in the wrong order. |
| constexpr uint8_t kSST210[] = { |
| 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x2d, 0x4c, 0x42, 0x52, |
| 0x32, 0x31, 0x50, 0x43, 0x0c, 0x2b, 0x03, 0x01, 0x33, 0x80, 0xa2, 0x20, |
| 0x56, 0x2a, 0x9c, 0x4e, 0x50, 0x5b, 0x26, 0x95, 0x50, 0x23, 0xbf, 0x59, |
| 0x80, 0xef, 0x80, 0x81, 0x59, 0x61, 0x59, 0x45, 0x59, 0x31, 0x40, 0x31, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x32, 0x8c, 0xa0, 0x40, 0xb0, 0x60, |
| 0x40, 0x19, 0x32, 0x1e, 0x00, 0x13, 0x44, 0x06, 0x00, 0x21, 0x1e, 0x00, |
| 0x00, 0x00, 0xfd, 0x00, 0x38, 0x00, 0x1e, 0x55, 0x0f, 0x51, 0x0a, 0x00, |
| 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0xfc, 0x00, 0x32, 0x00, |
| 0x30, 0x31, 0x20, 0x54, 0x69, 0x44, 0x69, 0x67, 0x61, 0x74, 0x0a, 0x6c, |
| 0x00, 0x00, 0xff, 0x00, 0x48, 0x00, 0x4b, 0x34, 0x41, 0x54, 0x30, 0x30, |
| 0x32, 0x38, 0x0a, 0x38, 0x20, 0x20, 0xf8, 0x00}; |
| |
| // EDID of |kSST210| with the order of the primaries corrected. Still invalid |
| // because the triangle of primaries is too small. |
| constexpr uint8_t kSST210Corrected[] = { |
| 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x2d, 0x4c, 0x42, 0x52, |
| 0x32, 0x31, 0x50, 0x43, 0x0c, 0x2b, 0x03, 0x01, 0x33, 0x80, 0xa2, 0x20, |
| 0x56, 0x2a, 0x9c, 0x95, 0x50, 0x4e, 0x50, 0x5b, 0x26, 0x23, 0xbf, 0x59, |
| 0x80, 0xef, 0x80, 0x81, 0x59, 0x61, 0x59, 0x45, 0x59, 0x31, 0x40, 0x31, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x32, 0x8c, 0xa0, 0x40, 0xb0, 0x60, |
| 0x40, 0x19, 0x32, 0x1e, 0x00, 0x13, 0x44, 0x06, 0x00, 0x21, 0x1e, 0x00, |
| 0x00, 0x00, 0xfd, 0x00, 0x38, 0x00, 0x1e, 0x55, 0x0f, 0x51, 0x0a, 0x00, |
| 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0xfc, 0x00, 0x32, 0x00, |
| 0x30, 0x31, 0x20, 0x54, 0x69, 0x44, 0x69, 0x67, 0x61, 0x74, 0x0a, 0x6c, |
| 0x00, 0x00, 0xff, 0x00, 0x48, 0x00, 0x4b, 0x34, 0x41, 0x54, 0x30, 0x30, |
| 0x32, 0x38, 0x0a, 0x38, 0x20, 0x20, 0xf8, 0x00}; |
| |
| // This EDID produces blue primary coordinates too far off the expected point, |
| // which would paint blue colors as purple. See https://crbug.com/809909. |
| constexpr uint8_t kBrokenBluePrimaries[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x83, 0x4d, 0x83, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x01, 0x04, 0x95, 0x1d, 0x10, 0x78, |
| 0x0a, 0xee, 0x25, 0xa3, 0x54, 0x4c, 0x99, 0x29, 0x26, 0x50, 0x54, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xd2, 0x37, 0x80, 0xa2, 0x70, 0x38, |
| 0x40, 0x40, 0x30, 0x20, 0x25, 0x00, 0x25, 0xa5, 0x10, 0x00, 0x00, 0x1a, |
| 0xa6, 0x2c, 0x80, 0xa2, 0x70, 0x38, 0x40, 0x40, 0x30, 0x20, 0x25, 0x00, |
| 0x25, 0xa5, 0x10, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x56, |
| 0x59, 0x54, 0x39, 0x36, 0x80, 0x31, 0x33, 0x33, 0x48, 0x4c, 0x0a, 0x20, |
| 0x00, 0x00, 0x00, 0x00}; |
| |
| // This EDID contains Short Audio Descriptors in the Timing Extension |
| // Data which indicate LPCM, DTS, and DTS-HD audio. |
| constexpr uint8_t kDTSAudio[] = { |
| 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x59, 0x3a, 0x39, 0x10, |
| 0x01, 0x01, 0x01, 0x01, 0x00, 0x1f, 0x01, 0x03, 0x80, 0x5e, 0x35, 0x78, |
| 0x2a, 0x29, 0xdd, 0xa5, 0x57, 0x35, 0x9f, 0x26, 0x0e, 0x47, 0x4a, 0xa5, |
| 0xce, 0x00, 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, |
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0xe8, 0x00, 0x30, 0xf2, 0x70, |
| 0x5a, 0x80, 0xb0, 0x58, 0x8a, 0x00, 0xad, 0x11, 0x32, 0x00, 0x00, 0x1e, |
| 0x56, 0x5e, 0x00, 0xa0, 0xa0, 0xa0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, |
| 0xad, 0x11, 0x32, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x56, |
| 0x34, 0x33, 0x35, 0x2d, 0x4a, 0x30, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, |
| 0x00, 0x00, 0x00, 0xfd, 0x00, 0x17, 0x4c, 0x0f, 0x8c, 0x3c, 0x00, 0x0a, |
| 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xb3, 0x02, 0x03, 0x75, 0x70, |
| 0x57, 0x61, 0x66, 0x5f, 0x64, 0x5d, 0x62, 0x60, 0x65, 0x5e, 0x63, 0x10, |
| 0x22, 0x20, 0x1f, 0x21, 0x05, 0x04, 0x13, 0x07, 0x06, 0x03, 0x02, 0x01, |
| 0x35, 0x09, 0x07, 0x07, 0x15, 0x07, 0x50, 0x57, 0x04, 0x03, 0x3d, 0x07, |
| 0xc0, 0x5f, 0x7e, 0x07, 0x67, 0x7e, 0x03, 0x5f, 0x7e, 0x01, 0x83, 0x01, |
| 0x00, 0x00, 0x70, 0x03, 0x0c, 0x00, 0x20, 0x00, 0x38, 0x44, 0xa0, 0x5b, |
| 0x5b, 0x00, 0x80, 0x01, 0x02, 0x03, 0x04, 0x6a, 0xd8, 0x5d, 0xc4, 0x01, |
| 0x78, 0x80, 0x0b, 0x02, 0x00, 0x00, 0xeb, 0x01, 0x46, 0xd0, 0x00, 0x4d, |
| 0x4f, 0x2a, 0x96, 0x38, 0x1f, 0xbf, 0xe5, 0x01, 0x8b, 0x84, 0x90, 0x01, |
| 0xe2, 0x00, 0xff, 0xe2, 0x0f, 0xc3, 0xe6, 0x06, 0x0f, 0x01, 0x53, 0x53, |
| 0x0a, 0xe3, 0x05, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x80}; |
| |
| } // namespace |
| |
| TEST(DisplayUtilTest, TestValidDisplaySize) { |
| EXPECT_FALSE(IsDisplaySizeValid(gfx::Size(10, 10))); |
| EXPECT_FALSE(IsDisplaySizeValid(gfx::Size(40, 30))); |
| EXPECT_FALSE(IsDisplaySizeValid(gfx::Size(50, 40))); |
| EXPECT_FALSE(IsDisplaySizeValid(gfx::Size(160, 90))); |
| EXPECT_FALSE(IsDisplaySizeValid(gfx::Size(160, 100))); |
| |
| EXPECT_TRUE(IsDisplaySizeValid(gfx::Size(50, 60))); |
| EXPECT_TRUE(IsDisplaySizeValid(gfx::Size(100, 70))); |
| EXPECT_TRUE(IsDisplaySizeValid(gfx::Size(272, 181))); |
| } |
| |
| TEST(DisplayUtilTest, GetColorSpaceFromEdid) { |
| base::HistogramTester histogram_tester; |
| |
| // Test with HP z32x monitor. |
| constexpr SkColorSpacePrimaries expected_hpz32x_primaries = { |
| .fRX = 0.673828f, |
| .fRY = 0.316406f, |
| .fGX = 0.198242f, |
| .fGY = 0.719727f, |
| .fBX = 0.148438f, |
| .fBY = 0.043945f, |
| .fWX = 0.313477f, |
| .fWY = 0.329102f}; |
| skcms_Matrix3x3 expected_hpz32x_toXYZ50_matrix; |
| expected_hpz32x_primaries.toXYZD50(&expected_hpz32x_toXYZ50_matrix); |
| std::vector<uint8_t> hpz32x_edid(std::begin(kHPz32x), std::end(kHPz32x)); |
| const gfx::ColorSpace expected_hpz32x_color_space = |
| gfx::ColorSpace::CreateCustom( |
| expected_hpz32x_toXYZ50_matrix, |
| skcms_TransferFunction({2.2, 1, 0, 0, 0, 0, 0})); |
| EXPECT_EQ(expected_hpz32x_color_space.ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(hpz32x_edid))) |
| .ToString()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kSuccess), |
| 1); |
| |
| // Test with Chromebook Samus internal display. |
| constexpr SkColorSpacePrimaries expected_samus_primaries = {.fRX = 0.633789f, |
| .fRY = 0.347656f, |
| .fGX = 0.323242f, |
| .fGY = 0.577148f, |
| .fBX = 0.151367f, |
| .fBY = 0.090820f, |
| .fWX = 0.313477f, |
| .fWY = 0.329102f}; |
| skcms_Matrix3x3 expected_samus_toXYZ50_matrix; |
| expected_samus_primaries.toXYZD50(&expected_samus_toXYZ50_matrix); |
| std::vector<uint8_t> samus_edid(std::begin(kSamus), std::end(kSamus)); |
| const gfx::ColorSpace expected_samus_color_space = |
| gfx::ColorSpace::CreateCustom( |
| expected_samus_toXYZ50_matrix, |
| skcms_TransferFunction({2.5, 1, 0, 0, 0, 0, 0})); |
| EXPECT_EQ(expected_samus_color_space.ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(samus_edid))) |
| .ToString()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kSuccess), |
| 2); |
| |
| // Test with Chromebook Eve internal display. The SkColorSpacePrimaries: |
| // SkColorSpacePrimaries expected_eve_primaries = {.fRX = 0.639648f, |
| // .fRY = 0.329102f, |
| // .fGX = 0.299805f, |
| // .fGY = 0.599609f, |
| // .fBX = 0.149414f, |
| // .fBY = 0.059570f, |
| // .fWX = 0.312500f, |
| // .fWY = 0.328125f}; |
| // are very close to the BT.709/sRGB ones, so they'll be rounded to those. |
| const skcms_TransferFunction eve_transfer({2.2, 1, 0, 0, 0, 0, 0}); |
| const gfx::ColorSpace expected_eve_color_space( |
| gfx::ColorSpace::PrimaryID::BT709, gfx::ColorSpace::TransferID::CUSTOM, |
| gfx::ColorSpace::MatrixID::RGB, gfx::ColorSpace::RangeID::FULL, |
| /*custom_primary_matrix=*/nullptr, &eve_transfer); |
| std::vector<uint8_t> eve_edid(std::begin(kEve), std::end(kEve)); |
| EXPECT_EQ(expected_eve_color_space.ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(eve_edid))) |
| .ToString()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kSuccess), |
| 3); |
| |
| // Test with a display that supports HDR: Chromebook Samsung Galaxy (kohaku). |
| constexpr SkColorSpacePrimaries expected_hdr_primaries = {.fRX = 0.67970f, |
| .fRY = 0.31930f, |
| .fGX = 0.23240f, |
| .fGY = 0.71870f, |
| .fBX = 0.13965f, |
| .fBY = 0.04390f, |
| .fWX = 0.31250f, |
| .fWY = 0.32910f}; |
| skcms_Matrix3x3 expected_hdr_toXYZ50_matrix; |
| expected_hdr_primaries.toXYZD50(&expected_hdr_toXYZ50_matrix); |
| std::vector<uint8_t> hdr_edid(std::begin(kHDR), std::end(kHDR)); |
| const gfx::ColorSpace expected_hdr_color_space = |
| gfx::ColorSpace::CreateCustom(expected_hdr_toXYZ50_matrix, |
| gfx::ColorSpace::TransferID::PQ); |
| EXPECT_TRUE(expected_hdr_color_space.IsHDR()); |
| EXPECT_EQ(expected_hdr_color_space.ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(hdr_edid))) |
| .ToString()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kSuccess), |
| 4); |
| |
| // Test with gamma marked as non-existent. |
| std::vector<uint8_t> no_gamma_edid(std::begin(kEdidWithNoGamma), |
| std::end(kEdidWithNoGamma)); |
| const gfx::ColorSpace no_gamma_color_space = |
| GetColorSpaceFromEdid(display::EdidParser(std::move(no_gamma_edid))); |
| EXPECT_FALSE(no_gamma_color_space.IsValid()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorBadGamma), |
| 1); |
| histogram_tester.ExpectTotalCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", 5); |
| |
| // Test with a display with primaries near P3, but {BT2020,RGB} in its CDB. |
| constexpr SkColorSpacePrimaries expected_p3_primaries = {.fRX = 0.680f, |
| .fRY = 0.320f, |
| .fGX = 0.265f, |
| .fGY = 0.690f, |
| .fBX = 0.150f, |
| .fBY = 0.060f, |
| .fWX = 0.3127, |
| .fWY = 0.3290}; |
| skcms_Matrix3x3 expected_p3_to_XYZ50_matrix; |
| expected_p3_primaries.toXYZD50(&expected_p3_to_XYZ50_matrix); |
| std::vector<uint8_t> p3_edid(std::begin(kScreeboP3), std::end(kScreeboP3)); |
| const gfx::ColorSpace expected_p3_color_space = gfx::ColorSpace::CreateCustom( |
| expected_p3_to_XYZ50_matrix, gfx::ColorSpace::TransferID::PQ); |
| EXPECT_TRUE(expected_p3_color_space.IsWide()); |
| // Expect P3 primaries and PQ transfer function. |
| EXPECT_EQ(expected_p3_color_space.ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(p3_edid))) |
| .ToString()); |
| |
| // Test with a display that has only DCI-P3 in its Colorimetry Data Block. |
| std::vector<uint8_t> p3_cdb_edid(std::begin(kCDBP3), std::end(kCDBP3)); |
| EXPECT_EQ( |
| gfx::ColorSpace::CreateDisplayP3D65().ToString(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(p3_cdb_edid), true)) |
| .ToString()); |
| } |
| |
| TEST(DisplayUtilTest, GetInvalidColorSpaceFromEdid) { |
| base::HistogramTester histogram_tester; |
| std::vector<uint8_t> empty_edid; |
| EXPECT_EQ(gfx::ColorSpace(), |
| GetColorSpaceFromEdid(display::EdidParser(std::move(empty_edid)))); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorPrimariesAreaTooSmall), |
| 1); |
| |
| std::vector<uint8_t> invalid_edid(std::begin(kInvalidEdid), |
| std::end(kInvalidEdid)); |
| const gfx::ColorSpace invalid_color_space = |
| GetColorSpaceFromEdid(display::EdidParser(std::move(invalid_edid))); |
| EXPECT_FALSE(invalid_color_space.IsValid()); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorPrimariesAreaTooSmall), |
| 2); |
| |
| std::vector<uint8_t> sst210_edid(std::begin(kSST210), std::end(kSST210)); |
| const gfx::ColorSpace sst210_color_space = |
| GetColorSpaceFromEdid(display::EdidParser(std::move(sst210_edid))); |
| EXPECT_FALSE(sst210_color_space.IsValid()) << sst210_color_space.ToString(); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorBadCoordinates), |
| 1); |
| |
| std::vector<uint8_t> sst210_edid_2(std::begin(kSST210Corrected), |
| std::end(kSST210Corrected)); |
| const gfx::ColorSpace sst210_color_space_2 = |
| GetColorSpaceFromEdid(display::EdidParser(std::move(sst210_edid_2))); |
| EXPECT_FALSE(sst210_color_space_2.IsValid()) |
| << sst210_color_space_2.ToString(); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorPrimariesAreaTooSmall), |
| 3); |
| |
| std::vector<uint8_t> broken_blue_edid(std::begin(kBrokenBluePrimaries), |
| std::end(kBrokenBluePrimaries)); |
| const gfx::ColorSpace broken_blue_color_space = |
| GetColorSpaceFromEdid(display::EdidParser(std::move(broken_blue_edid))); |
| EXPECT_FALSE(broken_blue_color_space.IsValid()) |
| << broken_blue_color_space.ToString(); |
| histogram_tester.ExpectBucketCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", |
| static_cast<base::HistogramBase::Sample32>( |
| EdidColorSpaceChecksOutcome::kErrorBluePrimaryIsBroken), |
| 1); |
| histogram_tester.ExpectTotalCount( |
| "DrmUtil.GetColorSpaceFromEdid.ChecksOutcome", 5); |
| } |
| |
| TEST(DisplayUtilTest, GetAudioPassthroughFromEdid) { |
| std::vector<uint8_t> audio_edid(std::begin(kDTSAudio), std::end(kDTSAudio)); |
| EXPECT_EQ(display::EdidParser(std::move(audio_edid)).audio_formats(), |
| display::EdidParser::kAudioBitstreamPcmLinear | |
| display::EdidParser::kAudioBitstreamDts | |
| display::EdidParser::kAudioBitstreamDtsHd); |
| } |
| |
| TEST(DisplayUtilTest, MultipleInternalDisplayIds) { |
| // using base::flat_set as base::FixedFlatSet with different N are different |
| // types. |
| const base::flat_set<int64_t> kTestIdsList[] = { |
| base::flat_set<int64_t>({1}), |
| base::flat_set<int64_t>({2, 3}), |
| base::flat_set<int64_t>({4, 5, 6}), |
| base::flat_set<int64_t>( |
| {7, 10, 100, std::numeric_limits<int64_t>::max()}), |
| }; |
| |
| int64_t from_last_set = 0; |
| for (const auto& id_set : kTestIdsList) { |
| SetInternalDisplayIds(id_set); |
| for (int64_t id : id_set) { |
| EXPECT_TRUE(IsInternalDisplayId(id)); |
| } |
| EXPECT_FALSE(IsInternalDisplayId(from_last_set)); |
| from_last_set = *id_set.rbegin(); |
| } |
| |
| // Reset the internal display. |
| SetInternalDisplayIds({}); |
| for (auto id_set : kTestIdsList) { |
| for (int64_t id : id_set) { |
| EXPECT_FALSE(IsInternalDisplayId(id)); |
| } |
| } |
| } |
| |
| TEST(DisplayUtilTest, CompareDisplayIdsWithMultipleDisplays) { |
| // Internal display is always first. |
| EXPECT_TRUE(CompareDisplayIds(10, 12)); |
| { |
| ScopedSetInternalDisplayIds set_internal(10); |
| EXPECT_TRUE(CompareDisplayIds(10, 12)); |
| EXPECT_TRUE(CompareDisplayIds(10, 9)); |
| EXPECT_TRUE(CompareDisplayIds(10, 15)); |
| EXPECT_FALSE(CompareDisplayIds(12, 10)); |
| EXPECT_FALSE(CompareDisplayIds(12, 9)); |
| EXPECT_TRUE(CompareDisplayIds(12, 15)); |
| } |
| { |
| ScopedSetInternalDisplayIds set_internal(12); |
| EXPECT_FALSE(CompareDisplayIds(10, 12)); |
| EXPECT_FALSE(CompareDisplayIds(10, 9)); |
| EXPECT_TRUE(CompareDisplayIds(10, 15)); |
| EXPECT_TRUE(CompareDisplayIds(12, 10)); |
| EXPECT_TRUE(CompareDisplayIds(12, 9)); |
| EXPECT_TRUE(CompareDisplayIds(12, 15)); |
| } |
| // Internal displays are always first but compares values between internal |
| // displays. |
| { |
| ScopedSetInternalDisplayIds set_internal({12, 10}); |
| EXPECT_TRUE(CompareDisplayIds(10, 12)); |
| EXPECT_TRUE(CompareDisplayIds(10, 9)); |
| EXPECT_TRUE(CompareDisplayIds(10, 15)); |
| EXPECT_FALSE(CompareDisplayIds(12, 10)); |
| EXPECT_TRUE(CompareDisplayIds(12, 9)); |
| EXPECT_TRUE(CompareDisplayIds(12, 15)); |
| } |
| } |
| |
| } // namespace display |