Commit f8a95994 authored by Miguel Casas's avatar Miguel Casas Committed by Commit Bot

display: ignore EDID-provided colorspace if blue is broken

Some EDID-provided chromaticity coordinates for the blue colour are
too far from the expected ones, causing blue to be rendered as purple
(or cyan, in some cases). This is due to broken primaries, as all the
standard colorspaces' blues are clustered nearby.

This CL adds a sanity check for the blue coordinates (need to be to
the left and below of a given point) and adds a unit test for it. If
the condition doesn't verify, we just ignore this ColorSpace -- which
means we'll treat the monitor as sRGB.

Bug: 809909, 771345
Change-Id: I4555625928f883825a3b315abdaaa379eb26a415
Reviewed-on: https://chromium-review.googlesource.com/993513
Commit-Queue: Miguel Casas <mcasas@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548138}
parent 7c2240a7
......@@ -660,6 +660,19 @@ gfx::ColorSpace GetColorSpaceFromEdid(const std::vector<uint8_t>& edid) {
if (primaries_area_twice < kBT709PrimariesArea)
return gfx::ColorSpace();
// Sanity check: https://crbug.com/809909, the blue primary coordinates should
// not be too far left/upwards of the expected location (namely [0.15, 0.06]
// for sRGB/ BT.709/ Adobe RGB/ DCI-P3, and [0.131, 0.046] for BT.2020).
constexpr float kExpectedBluePrimaryX = 0.15f;
constexpr float kBluePrimaryXDelta = 0.02f;
constexpr float kExpectedBluePrimaryY = 0.06f;
constexpr float kBluePrimaryYDelta = 0.031f;
const bool is_blue_primary_broken =
(std::abs(primaries.fBX - kExpectedBluePrimaryX) > kBluePrimaryXDelta) ||
(std::abs(primaries.fBY - kExpectedBluePrimaryY) > kBluePrimaryYDelta);
if (is_blue_primary_broken)
return gfx::ColorSpace();
SkMatrix44 color_space_as_matrix;
if (!primaries.toXYZD50(&color_space_as_matrix))
return gfx::ColorSpace();
......
......@@ -93,6 +93,17 @@ const unsigned char kSST210Corrected[] =
"\x30\x31\x20\x54\x69\x44\x69\x67\x61\x74\x0a\x6c\x00\x00\xff\x00"
"\x48\x00\x4b\x34\x41\x54\x30\x30\x32\x38\x0a\x38\x20\x20\xf8\x00";
// This EDID produces blue primary coordinates too far off the expected point,
// which would paint blue colors as purple. See https://crbug.com/809909.
const unsigned char kBrokenBluePrimaries[] =
"\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x83\x4d\x83\x00\x00\x00\x00"
"\x00\x19\x01\x04\x95\x1d\x10\x78\x0a\xee\x25\xa3\x54\x4c\x99\x29"
"\x26\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
"\x01\x01\x01\x01\x01\x01\xd2\x37\x80\xa2\x70\x38\x40\x40\x30\x20"
"\x25\x00\x25\xa5\x10\x00\x00\x1a\xa6\x2c\x80\xa2\x70\x38\x40\x40"
"\x30\x20\x25\x00\x25\xa5\x10\x00\x00\x1a\x00\x00\x00\xfe\x00\x56"
"\x59\x54\x39\x36\x80\x31\x33\x33\x48\x4c\x0a\x20\x00\x00\x00\x00";
} // anonymous namespace
bool operator==(const ui::DisplayMode_Params& a,
......@@ -356,6 +367,14 @@ TEST_F(DrmUtilTest, GetInvalidColorSpaceFromEdid) {
GetColorSpaceFromEdid(sst210_edid_2);
EXPECT_FALSE(sst210_color_space_2.IsValid())
<< sst210_color_space_2.ToString();
const std::vector<uint8_t> broken_blue_edid(
kBrokenBluePrimaries,
kBrokenBluePrimaries + arraysize(kBrokenBluePrimaries) - 1);
const gfx::ColorSpace broken_blue_color_space =
GetColorSpaceFromEdid(broken_blue_edid);
EXPECT_FALSE(broken_blue_color_space.IsValid())
<< broken_blue_color_space.ToString();
}
TEST_F(DrmUtilTest, TestDisplayModesExtraction) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment