Changeset 226898 in webkit


Ignore:
Timestamp:
Jan 12, 2018 10:30:06 AM (6 years ago)
Author:
jer.noble@apple.com
Message:

WebGL video texture black in Safari 11.0.2 and wrong colored in Safari Preview 11.1
https://bugs.webkit.org/show_bug.cgi?id=181445
<rdar://problem/36383183>

Reviewed by Dean Jackson.

Tests: added compile-time correctness tests for YCbCrMatrix values.

Perform the derivation from YCbCr coefficients into matrices in constexpr expressions
at compile-time. This allows us to also perform compile-time correctness checks to catch
regressions which may cause incorrect color conversions.

Since we now have general-purpose derivation of matrix values from coefficients,
adding missing specificed matrices is trivial, so add support for SMPTE 240M and BT.2020
matrices.

  • platform/graphics/cv/VideoTextureCopierCV.cpp:

(WebCore::GLfloatColor::GLfloatColor):
(WebCore::GLfloatColor::abs):
(WebCore::GLfloatColor::isApproximatelyEqualTo const):
(WebCore::YCbCrMatrix::operator Vector<GLfloat> const):
(WebCore::YCbCrMatrix::YCbCrMatrix):
(WebCore::YCbCrMatrix::operator* const):
(WebCore::YCbCrToRGBMatrixForRangeAndTransferFunction):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r226886 r226898  
     12018-01-12  Jer Noble  <jer.noble@apple.com>
     2
     3        WebGL video texture black in Safari 11.0.2 and wrong colored in Safari Preview 11.1
     4        https://bugs.webkit.org/show_bug.cgi?id=181445
     5        <rdar://problem/36383183>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Tests: added compile-time correctness tests for YCbCrMatrix values.
     10
     11        Perform the derivation from YCbCr coefficients into matrices in constexpr expressions
     12        at compile-time. This allows us to also perform compile-time correctness checks to catch
     13        regressions which may cause incorrect color conversions.
     14
     15        Since we now have general-purpose derivation of matrix values from coefficients,
     16        adding missing specificed matrices is trivial, so add support for SMPTE 240M and BT.2020
     17        matrices.
     18
     19        * platform/graphics/cv/VideoTextureCopierCV.cpp:
     20        (WebCore::GLfloatColor::GLfloatColor):
     21        (WebCore::GLfloatColor::abs):
     22        (WebCore::GLfloatColor::isApproximatelyEqualTo const):
     23        (WebCore::YCbCrMatrix::operator Vector<GLfloat> const):
     24        (WebCore::YCbCrMatrix::YCbCrMatrix):
     25        (WebCore::YCbCrMatrix::operator* const):
     26        (WebCore::YCbCrToRGBMatrixForRangeAndTransferFunction):
     27
    1282018-01-12  Antoine Quint  <graouts@apple.com>
    229
  • trunk/Source/WebCore/platform/graphics/cv/VideoTextureCopierCV.cpp

    r225638 r226898  
    112112}
    113113
     114struct GLfloatColor {
     115    union {
     116        struct {
     117            GLfloat r;
     118            GLfloat g;
     119            GLfloat b;
     120        } rgb;
     121        struct {
     122            GLfloat y;
     123            GLfloat cb;
     124            GLfloat cr;
     125        } ycbcr;
     126    };
     127
     128    constexpr GLfloatColor(GLfloat r, GLfloat g, GLfloat b)
     129        : rgb { r, g, b }
     130    {
     131    }
     132
     133    constexpr GLfloatColor(int r, int g, int b, GLfloat scale)
     134        : rgb { r / scale, g / scale, b / scale}
     135    {
     136    }
     137
     138    static constexpr GLfloat abs(GLfloat value)
     139    {
     140        return value >= 0 ? value : -value;
     141    }
     142
     143    constexpr bool isApproximatelyEqualTo(const GLfloatColor& color, GLfloat maxDelta) const
     144    {
     145        return abs(rgb.r - color.rgb.r) < abs(maxDelta)
     146            && abs(rgb.g - color.rgb.g) < abs(maxDelta)
     147            && abs(rgb.b - color.rgb.b) < abs(maxDelta);
     148    }
     149};
     150
     151struct GLfloatColors {
     152    static constexpr GLfloatColor black   {0, 0, 0};
     153    static constexpr GLfloatColor white   {1, 1, 1};
     154    static constexpr GLfloatColor red     {1, 0, 0};
     155    static constexpr GLfloatColor green   {0, 1, 0};
     156    static constexpr GLfloatColor blue    {0, 0, 1};
     157    static constexpr GLfloatColor cyan    {0, 1, 1};
     158    static constexpr GLfloatColor magenta {1, 0, 1};
     159    static constexpr GLfloatColor yellow  {1, 1, 0};
     160};
     161
     162struct YCbCrMatrix {
     163    union {
     164        GLfloat rows[4][4];
     165        GLfloat data[16];
     166    };
     167
     168    constexpr YCbCrMatrix(PixelRange, GLfloat cbCoefficient, GLfloat crCoefficient);
     169
     170    operator Vector<GLfloat>() const
     171    {
     172        Vector<GLfloat> vector;
     173        vector.append(data, 16);
     174        return vector;
     175    }
     176
     177    constexpr GLfloatColor operator*(const GLfloatColor&) const;
     178};
     179
     180constexpr YCbCrMatrix::YCbCrMatrix(PixelRange range, GLfloat cbCoefficient, GLfloat crCoefficient)
     181    : rows { }
     182{
     183    // The conversion from YCbCr -> RGB generally takes the form:
     184    // Y = Kr * R + Kg * G + Kb * B
     185    // Cb = (B - Y) / (2 * (1 - Kb))
     186    // Cr = (R - Y) / (2 * (1 - Kr))
     187    // Where the values of Kb and Kr are defined in a specification and Kg is derived from: Kr + Kg + Kb = 1
     188    //
     189    // Solving the above equations for R, B, and G derives the following:
     190    // R = Y + (2 * (1 - Kr)) * Cr
     191    // B = Y + (2 * (1 - Kb)) * Cb
     192    // G = Y - (2 * (1 - Kb)) * (Kb / Kg) * Cb - ((1 - Kr) * 2) * (Kr / Kg) * Cr
     193    //
     194    // When the color values are Video range, Y has a range of [16, 235] with a width of 219, and Cb & Cr have
     195    // a range of [16, 240] with a width of 224. When the color values are Full range, Y, Cb, and Cr all have
     196    // a range of [0, 255] with a width of 256.
     197
     198    GLfloat cgCoefficient = 1 - cbCoefficient - crCoefficient;
     199    GLfloat yScalingFactor = range == PixelRange::Full ? 1.f : 255.f / 219.f;
     200    GLfloat cbcrScalingFactor = range == PixelRange::Full ? 1.f : 255.f / 224.f;
     201
     202    rows[0][0] = yScalingFactor;
     203    rows[0][1] = 0;
     204    rows[0][2] = cbcrScalingFactor * 2 * (1 - crCoefficient);
     205    rows[0][3] = 0;
     206
     207    rows[1][0] = yScalingFactor;
     208    rows[1][1] = -cbcrScalingFactor * 2 * (1 - cbCoefficient) * (cbCoefficient / cgCoefficient);
     209    rows[1][2] = -cbcrScalingFactor * 2 * (1 - crCoefficient) * (crCoefficient / cgCoefficient);
     210    rows[1][3] = 0;
     211
     212    rows[2][0] = yScalingFactor;
     213    rows[2][1] = cbcrScalingFactor * 2 * (1 - cbCoefficient);
     214    rows[2][2] = 0;
     215    rows[2][3] = 0;
     216
     217    rows[3][0] = 0;
     218    rows[3][1] = 0;
     219    rows[3][2] = 0;
     220    rows[3][3] = 1;
     221
     222    // Configure the final column of the matrix to convert Cb and Cr to [-128, 128]
     223    // and, in the case of video-range, to convert Y to [16, 240]:
     224    for (auto rowNumber = 0; rowNumber < 3; ++rowNumber) {
     225        auto& row = rows[rowNumber];
     226        auto& x = row[0];
     227        auto& y = row[1];
     228        auto& z = row[2];
     229        auto& w = row[3];
     230
     231        w -= (y + z) * 128 / 255;
     232        if (range == PixelRange::Video)
     233            w -= x * 16 / 255;
     234    }
     235}
     236
     237constexpr GLfloatColor YCbCrMatrix::operator*(const GLfloatColor& color) const
     238{
     239    return GLfloatColor(
     240        rows[0][0] * color.rgb.r + rows[0][1] * color.rgb.g + rows[0][2] * color.rgb.b + rows[0][3],
     241        rows[1][0] * color.rgb.r + rows[1][1] * color.rgb.g + rows[1][2] * color.rgb.b + rows[1][3],
     242        rows[2][0] * color.rgb.r + rows[2][1] * color.rgb.g + rows[2][2] * color.rgb.b + rows[2][3]
     243    );
     244}
     245
    114246static const Vector<GLfloat> YCbCrToRGBMatrixForRangeAndTransferFunction(PixelRange range, TransferFunction transferFunction)
    115247{
     
    119251    static NeverDestroyed<MatrixMap> matrices;
    120252    static dispatch_once_t onceToken;
     253
     254    // Matrices are derived from the components in the ITU R.601 rev 4 specification
     255    // https://www.itu.int/rec/R-REC-BT.601
     256    constexpr static YCbCrMatrix r601VideoMatrix { PixelRange::Video, 0.114f, 0.299f };
     257    constexpr static YCbCrMatrix r601FullMatrix { PixelRange::Full, 0.114f, 0.299f };
     258
     259    static_assert((r601VideoMatrix * GLfloatColor(16,  128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "r.610 video matrix does not produce black color");
     260    static_assert((r601VideoMatrix * GLfloatColor(235, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "r.610 video matrix does not produce white color");
     261    static_assert((r601VideoMatrix * GLfloatColor(81,  90,  240, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "r.610 video matrix does not produce red color");
     262    static_assert((r601VideoMatrix * GLfloatColor(145, 54,  34,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "r.610 video matrix does not produce green color");
     263    static_assert((r601VideoMatrix * GLfloatColor(41,  240, 110, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "r.610 video matrix does not produce blue color");
     264    static_assert((r601VideoMatrix * GLfloatColor(210, 16,  146, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "r.610 video matrix does not produce yellow color");
     265    static_assert((r601VideoMatrix * GLfloatColor(106, 202, 222, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "r.610 video matrix does not produce magenta color");
     266    static_assert((r601VideoMatrix * GLfloatColor(170, 166, 16,  255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "r.610 video matrix does not produce cyan color");
     267
     268    static_assert((r601FullMatrix * GLfloatColor(0,   128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "r.610 full matrix does not produce black color");
     269    static_assert((r601FullMatrix * GLfloatColor(255, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "r.610 full matrix does not produce white color");
     270    static_assert((r601FullMatrix * GLfloatColor(76,  85,  255, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "r.610 full matrix does not produce red color");
     271    static_assert((r601FullMatrix * GLfloatColor(150, 44,  21,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "r.610 full matrix does not produce green color");
     272    static_assert((r601FullMatrix * GLfloatColor(29,  255, 107, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "r.610 full matrix does not produce blue color");
     273    static_assert((r601FullMatrix * GLfloatColor(226, 0,   149, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "r.610 full matrix does not produce yellow color");
     274    static_assert((r601FullMatrix * GLfloatColor(105, 212, 235, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "r.610 full matrix does not produce magenta color");
     275    static_assert((r601FullMatrix * GLfloatColor(179, 171, 1,   255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "r.610 full matrix does not produce cyan color");
     276
     277    // Matrices are derived from the components in the ITU R.709 rev 2 specification
     278    // https://www.itu.int/rec/R-REC-BT.709-2-199510-S
     279    constexpr static YCbCrMatrix r709VideoMatrix { PixelRange::Video, 0.0722, 0.2126 };
     280    constexpr static YCbCrMatrix r709FullMatrix { PixelRange::Full, 0.0722, 0.2126 };
     281
     282    static_assert((r709VideoMatrix * GLfloatColor(16,  128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "r.709 video matrix does not produce black color");
     283    static_assert((r709VideoMatrix * GLfloatColor(235, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "r.709 video matrix does not produce white color");
     284    static_assert((r709VideoMatrix * GLfloatColor(63,  102, 240, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "r.709 video matrix does not produce red color");
     285    static_assert((r709VideoMatrix * GLfloatColor(173, 42,  26,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "r.709 video matrix does not produce green color");
     286    static_assert((r709VideoMatrix * GLfloatColor(32,  240, 118, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "r.709 video matrix does not produce blue color");
     287    static_assert((r709VideoMatrix * GLfloatColor(219, 16,  138, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "r.709 video matrix does not produce yellow color");
     288    static_assert((r709VideoMatrix * GLfloatColor(78,  214, 230, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "r.709 video matrix does not produce magenta color");
     289    static_assert((r709VideoMatrix * GLfloatColor(188, 154, 16,  255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "r.709 video matrix does not produce cyan color");
     290
     291    static_assert((r709FullMatrix * GLfloatColor(0,   128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "r.709 full matrix does not produce black color");
     292    static_assert((r709FullMatrix * GLfloatColor(255, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "r.709 full matrix does not produce white color");
     293    static_assert((r709FullMatrix * GLfloatColor(54,  99,  256, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "r.709 full matrix does not produce red color");
     294    static_assert((r709FullMatrix * GLfloatColor(182, 30,  12,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "r.709 full matrix does not produce green color");
     295    static_assert((r709FullMatrix * GLfloatColor(18,  256, 116, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "r.709 full matrix does not produce blue color");
     296    static_assert((r709FullMatrix * GLfloatColor(237, 1,   140, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "r.709 full matrix does not produce yellow color");
     297    static_assert((r709FullMatrix * GLfloatColor(73,  226, 244, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "r.709 full matrix does not produce magenta color");
     298    static_assert((r709FullMatrix * GLfloatColor(201, 157, 1,   255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "r.709 full matrix does not produce cyan color");
     299
     300    // Matrices are derived from the components in the ITU-R BT.2020-2 specification
     301    // https://www.itu.int/rec/R-REC-BT.2020
     302    constexpr static YCbCrMatrix bt2020VideoMatrix { PixelRange::Video, 0.0593, 0.2627 };
     303    constexpr static YCbCrMatrix bt2020FullMatrix { PixelRange::Full, 0.0593, 0.2627 };
     304
     305    static_assert((bt2020VideoMatrix * GLfloatColor(16,  128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "bt.2020 video matrix does not produce black color");
     306    static_assert((bt2020VideoMatrix * GLfloatColor(235, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "bt.2020 video matrix does not produce white color");
     307    static_assert((bt2020VideoMatrix * GLfloatColor(74,  97,  240, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "bt.2020 video matrix does not produce red color");
     308    static_assert((bt2020VideoMatrix * GLfloatColor(164, 47,  25,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "bt.2020 video matrix does not produce green color");
     309    static_assert((bt2020VideoMatrix * GLfloatColor(29,  240, 119, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "bt.2020 video matrix does not produce blue color");
     310    static_assert((bt2020VideoMatrix * GLfloatColor(222, 16,  137, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "bt.2020 video matrix does not produce yellow color");
     311    static_assert((bt2020VideoMatrix * GLfloatColor(87,  209, 231, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "bt.2020 video matrix does not produce magenta color");
     312    static_assert((bt2020VideoMatrix * GLfloatColor(177, 159, 16,  255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "bt.2020 video matrix does not produce cyan color");
     313
     314    static_assert((bt2020FullMatrix * GLfloatColor(0,   128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "bt.2020 full matrix does not produce black color");
     315    static_assert((bt2020FullMatrix * GLfloatColor(255, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "bt.2020 full matrix does not produce white color");
     316    static_assert((bt2020FullMatrix * GLfloatColor(67,  92,  256, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "bt.2020 full matrix does not produce red color");
     317    static_assert((bt2020FullMatrix * GLfloatColor(173, 36,  11,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "bt.2020 full matrix does not produce green color");
     318    static_assert((bt2020FullMatrix * GLfloatColor(15,  256, 118, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "bt.2020 full matrix does not produce blue color");
     319    static_assert((bt2020FullMatrix * GLfloatColor(240, 0,   138, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "bt.2020 full matrix does not produce yellow color");
     320    static_assert((bt2020FullMatrix * GLfloatColor(82,  220, 245, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "bt.2020 full matrix does not produce magenta color");
     321    static_assert((bt2020FullMatrix * GLfloatColor(188, 164, 1,   255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "bt.2020 full matrix does not produce cyan color");
     322
     323    // Matrices are derived from the components in the SMPTE 240M-1999 specification
     324    // http://ieeexplore.ieee.org/document/7291461/
     325    constexpr static YCbCrMatrix smpte240MVideoMatrix { PixelRange::Video, 0.087, 0.212 };
     326    constexpr static YCbCrMatrix smpte240MFullMatrix { PixelRange::Full, 0.087, 0.212 };
     327
     328    static_assert((smpte240MVideoMatrix * GLfloatColor(16,  128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "SMPTE 240M video matrix does not produce black color");
     329    static_assert((smpte240MVideoMatrix * GLfloatColor(235, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "SMPTE 240M video matrix does not produce white color");
     330    static_assert((smpte240MVideoMatrix * GLfloatColor(62,  102, 240, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "SMPTE 240M video matrix does not produce red color");
     331    static_assert((smpte240MVideoMatrix * GLfloatColor(170, 42,  28,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "SMPTE 240M video matrix does not produce green color");
     332    static_assert((smpte240MVideoMatrix * GLfloatColor(35,  240, 116, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "SMPTE 240M video matrix does not produce blue color");
     333    static_assert((smpte240MVideoMatrix * GLfloatColor(216, 16,  140, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "SMPTE 240M video matrix does not produce yellow color");
     334    static_assert((smpte240MVideoMatrix * GLfloatColor(81,  214, 228, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "SMPTE 240M video matrix does not produce magenta color");
     335    static_assert((smpte240MVideoMatrix * GLfloatColor(189, 154, 16,  255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "SMPTE 240M video matrix does not produce cyan color");
     336
     337    static_assert((smpte240MFullMatrix * GLfloatColor(0,   128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::black,   1.5f / 255.f), "SMPTE 240M full matrix does not produce black color");
     338    static_assert((smpte240MFullMatrix * GLfloatColor(255, 128, 128, 255)).isApproximatelyEqualTo(GLfloatColors::white,   1.5f / 255.f), "SMPTE 240M full matrix does not produce white color");
     339    static_assert((smpte240MFullMatrix * GLfloatColor(54,  98,  256, 255)).isApproximatelyEqualTo(GLfloatColors::red,     1.5f / 255.f), "SMPTE 240M full matrix does not produce red color");
     340    static_assert((smpte240MFullMatrix * GLfloatColor(179, 30,  15,  255)).isApproximatelyEqualTo(GLfloatColors::green,   1.5f / 255.f), "SMPTE 240M full matrix does not produce green color");
     341    static_assert((smpte240MFullMatrix * GLfloatColor(22,  256, 114, 255)).isApproximatelyEqualTo(GLfloatColors::blue,    1.5f / 255.f), "SMPTE 240M full matrix does not produce blue color");
     342    static_assert((smpte240MFullMatrix * GLfloatColor(233, 1,   142, 255)).isApproximatelyEqualTo(GLfloatColors::yellow,  1.5f / 255.f), "SMPTE 240M full matrix does not produce yellow color");
     343    static_assert((smpte240MFullMatrix * GLfloatColor(76,  226, 241, 255)).isApproximatelyEqualTo(GLfloatColors::magenta, 1.5f / 255.f), "SMPTE 240M full matrix does not produce magenta color");
     344    static_assert((smpte240MFullMatrix * GLfloatColor(201, 158, 1,   255)).isApproximatelyEqualTo(GLfloatColors::cyan,    1.5f / 255.f), "SMPTE 240M full matrix does not produce cyan color");
     345
    121346    dispatch_once(&onceToken, ^{
    122         // Matrices are derived from the components in the ITU R.601 rev 4 specification
    123         // https://www.itu.int/rec/R-REC-BT.601
    124         matrices.get().emplace(MapKey(PixelRange::Video, TransferFunction::kITU_R_601_4), Vector<GLfloat>({
    125             1.164383562f,  0.0f,           1.596026786f,  -0.874202218f,
    126             1.164383562f, -0.3917622901f, -0.8129676472f,  0.531667823f,
    127             1.164383562f,  2.017232143f,   0.0f,          -1.085630790f,
    128             0.0f,          0.0f,           0.0f,           1.0f,
    129         }));
    130         matrices.get().emplace(MapKey({PixelRange::Full, TransferFunction::kITU_R_601_4}), Vector<GLfloat>({
    131             1.000000000f,  0.0f,           1.4075196850f, -1.012571428f,
    132             1.000000000f, -0.3454911535f, -0.7169478464f,  0.533302714f,
    133             1.000000000f,  1.7789763780f,  0.0f,          -0.892976378f,
    134             0.0f,          0.0f,           0.0f,           1.0f,
    135         }));
    136         // Matrices are derived from the components in the ITU R.709 rev 2 specification
    137         // https://www.itu.int/rec/R-REC-BT.709-2-199510-S
    138         matrices.get().emplace(MapKey({PixelRange::Video, TransferFunction::kITU_R_709_2}), Vector<GLfloat>({
    139             1.164383562f,  0.0f,           1.792741071f,  -0.972945075f,
    140             1.164383562f, -0.2132486143f, -0.5329093286f,  0.301482665f,
    141             1.164383562f,  2.112401786f,   0.0f,          -1.133402218f,
    142             0.0f,          0.0f,           0.0f,           1.0f,
    143         }));
    144         matrices.get().emplace(MapKey({PixelRange::Full, TransferFunction::kITU_R_709_2}), Vector<GLfloat>({
    145             1.000000000f,  0.0f,           1.5810000000f, -0.793600000f,
    146             1.000000000f, -0.1880617701f, -0.4699672819f,  0.330304779f,
    147             1.000000000f,  1.8629055118f,  0.0f,          -0.935105512f,
    148             0.0f,          0.0f,           0.0f,           1.0f,
    149         }));
     347        matrices.get().emplace(MapKey(PixelRange::Video, TransferFunction::kITU_R_601_4), r601VideoMatrix);
     348        matrices.get().emplace(MapKey(PixelRange::Full, TransferFunction::kITU_R_601_4), r601FullMatrix);
     349        matrices.get().emplace(MapKey(PixelRange::Video, TransferFunction::kITU_R_709_2), r709VideoMatrix);
     350        matrices.get().emplace(MapKey(PixelRange::Full, TransferFunction::kITU_R_709_2), r709FullMatrix);
     351        matrices.get().emplace(MapKey(PixelRange::Video, TransferFunction::kITU_R_2020), bt2020VideoMatrix);
     352        matrices.get().emplace(MapKey(PixelRange::Full, TransferFunction::kITU_R_2020), bt2020FullMatrix);
     353        matrices.get().emplace(MapKey(PixelRange::Video, TransferFunction::kSMPTE_240M_1995), smpte240MVideoMatrix);
     354        matrices.get().emplace(MapKey(PixelRange::Full, TransferFunction::kSMPTE_240M_1995), smpte240MFullMatrix);
    150355    });
    151356
Note: See TracChangeset for help on using the changeset viewer.