SkColorSpaceXform.cpp revision 197e311ac9d15696fae929d8f5fcf9d93ec55e18
19876ac5b3016e5353c072378ac1545a0a2270757msarett/*
29876ac5b3016e5353c072378ac1545a0a2270757msarett * Copyright 2016 Google Inc.
39876ac5b3016e5353c072378ac1545a0a2270757msarett *
49876ac5b3016e5353c072378ac1545a0a2270757msarett * Use of this source code is governed by a BSD-style license that can be
59876ac5b3016e5353c072378ac1545a0a2270757msarett * found in the LICENSE file.
69876ac5b3016e5353c072378ac1545a0a2270757msarett */
79876ac5b3016e5353c072378ac1545a0a2270757msarett
89876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorPriv.h"
99488833428e83c93a7e6002f4d056084fb57112fraftias#include "SkColorSpace_A2B.h"
109876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorSpace_Base.h"
119488833428e83c93a7e6002f4d056084fb57112fraftias#include "SkColorSpace_XYZ.h"
12200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkColorSpacePriv.h"
132563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXform_A2B.h"
1431d097e865f266c8398f45114e4c75c0dfdef058msarett#include "SkColorSpaceXform_Base.h"
152563601fc2b0505619f905f86bd249ae630197ccraftias#include "SkColorSpaceXformPriv.h"
16200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkHalf.h"
17200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett#include "SkOpts.h"
18f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#include "SkRasterPipeline.h"
19ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h"
209876ac5b3016e5353c072378ac1545a0a2270757msarett
21f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_UNIX)
22f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarettstatic constexpr bool kUseRasterPipeline = true;
23f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#else
24f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarettstatic constexpr bool kUseRasterPipeline = false;
25f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#endif
26f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
276006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = {
28b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f,
29b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f,
30b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f,
31b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f,
32b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f,
33b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f,
34b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f,
35b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f,
36b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f,
37b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f,
38b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f,
39b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f,
40b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f,
41b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f,
42b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f,
43b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f,
44b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f,
45b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f,
46b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f,
47b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f,
48b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f,
49b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f,
50b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f,
51b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f,
52b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f,
53b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f,
54b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f,
55b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f,
56b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f,
57b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f,
58b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f,
59b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f,
60b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f,
61b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f,
62b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f,
63b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f,
64b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f,
65b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f,
66b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f,
67b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f,
68b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f,
69b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f,
70b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f,
71b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f,
72b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f,
73b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f,
74b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f,
75b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f,
76b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f,
77b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f,
78b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f,
79b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f,
80b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f,
81b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f,
82b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f,
83b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f,
84b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f,
85b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f,
86b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f,
87b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f,
88b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f,
89b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f,
90b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f,
91b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f,
92b39067696ad08a26bbe49b71a71f0546dc42a075msarett};
93b39067696ad08a26bbe49b71a71f0546dc42a075msarett
946006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
956006f678e78af7b6f67a454cd4bc213048983f9dmsarett
9615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) {
9715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
9815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = powf(x, exponent);
9915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
10115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
10215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// outTable is always 256 entries, inTable may be larger or smaller.
10315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable,
10415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          int inTableSize) {
10515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    if (256 == inTableSize) {
10615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        memcpy(outTable, inTable, sizeof(float) * 256);
10715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        return;
10815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
11015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
11115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = interp_lut(x, inTable, inTableSize);
11215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
11315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
11415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
115aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett
11615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c,
11715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          float d, float e, float f) {
11815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    // Y = (aX + b)^g + c  for X >= d
11915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    // Y = eX + f          otherwise
12015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
12115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        if (x >= d) {
122aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett            *outTable++ = clamp_0_1(powf(a * x + b, g) + c);
12315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        } else {
124aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett            *outTable++ = clamp_0_1(e * x + f);
12515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        }
12615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
12715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
12815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
12915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett///////////////////////////////////////////////////////////////////////////////////////////////////
13015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
131f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettstatic const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize;
1323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett
1331b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) {
134b39067696ad08a26bbe49b71a71f0546dc42a075msarett    float toGammaExp = 1.0f / exponent;
135b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1363418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1373418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
138b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp));
139b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
140dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett}
141dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
1421b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable,
143b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        int inTableSize) {
144197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias    invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize);
145b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
146dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
147b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e,
148b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                float f) {
149b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // We need to take the inverse of the following piecewise function.
150b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Y = (aX + b)^g + c  for X >= d
151b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Y = eX + f          otherwise
152b39067696ad08a26bbe49b71a71f0546dc42a075msarett
153b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Assume that the gamma function is continuous, or this won't make much sense anyway.
154b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Plug in |d| to the first equation to calculate the new piecewise interval.
155b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Then simply use the inverse of the original functions.
156b39067696ad08a26bbe49b71a71f0546dc42a075msarett    float interval = e * d + f;
157b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (x < interval) {
158b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // X = (Y - F) / E
159b39067696ad08a26bbe49b71a71f0546dc42a075msarett        if (0.0f == e) {
160b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // The gamma curve for this segment is constant, so the inverse is undefined.
161b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // Since this is the lower segment, guess zero.
162b39067696ad08a26bbe49b71a71f0546dc42a075msarett            return 0.0f;
163b39067696ad08a26bbe49b71a71f0546dc42a075msarett        }
164b39067696ad08a26bbe49b71a71f0546dc42a075msarett
165b39067696ad08a26bbe49b71a71f0546dc42a075msarett        return (x - f) / e;
166b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
167b39067696ad08a26bbe49b71a71f0546dc42a075msarett
168b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // X = ((Y - C)^(1 / G) - B) / A
169b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (0.0f == a || 0.0f == g) {
170b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // The gamma curve for this segment is constant, so the inverse is undefined.
171b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // Since this is the upper segment, guess one.
172b39067696ad08a26bbe49b71a71f0546dc42a075msarett        return 1.0f;
173b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
174b39067696ad08a26bbe49b71a71f0546dc42a075msarett
175b39067696ad08a26bbe49b71a71f0546dc42a075msarett    return (powf(x - c, 1.0f / g) - b) / a;
176b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
177b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1781b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a,
179b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        float b, float c, float d, float e, float f) {
1803418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1813418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
182b39067696ad08a26bbe49b71a71f0546dc42a075msarett        float y = inverse_parametric(x, g, a, b, c, d, e, f);
183b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(y);
184b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
185b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
186b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1876006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
1886006f678e78af7b6f67a454cd4bc213048983f9dmsarett
1891b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
1901b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns {
1911b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* fSRGBTable;
1921b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* f2Dot2Table;
1931b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromValue)(T*, float);
1941b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromTable)(T*, const float*, int);
1951b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromParam)(T*, float, float, float, float, float, float, float);
1961b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
1971b93bd1e6eba3d14593490e4e24a34546638c8damsarett
1981b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear {
1991b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_srgb,
2001b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_2dot2,
2011b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
2021b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
2031b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
2041b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2051b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2061b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear {
20755bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
20855bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
2091b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2101b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2111b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2121b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2131b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2141b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear.
2151b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
2161b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
2179488833428e83c93a7e6002f4d056084fb57112fraftias                               const SkColorSpace_XYZ* space, const GammaFns<T>& fns,
218f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                               bool gammasAreMatching)
2194be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett{
2209488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
221600c737b64eae2c7379442ae2c852853cce3a278msarett        case kSRGB_SkGammaNamed:
2221b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable;
2231b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
224600c737b64eae2c7379442ae2c852853cce3a278msarett        case k2Dot2Curve_SkGammaNamed:
2251b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table;
2261b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
227600c737b64eae2c7379442ae2c852853cce3a278msarett        case kLinear_SkGammaNamed:
2288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr;
2291b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
2301b93bd1e6eba3d14593490e4e24a34546638c8damsarett        default: {
2319488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
2321b93bd1e6eba3d14593490e4e24a34546638c8damsarett            SkASSERT(gammas);
2331b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2347bbda991af353fbe6b34132132d211d23a3dba8cmsarett            auto build_table = [=](int i) {
2351b93bd1e6eba3d14593490e4e24a34546638c8damsarett                if (gammas->isNamed(i)) {
2361b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    switch (gammas->data(i).fNamed) {
237600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kSRGB_SkGammaNamed:
23855bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], 2.4f,
23955bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                                                   (1.0f / 1.055f), (0.055f / 1.055f), 0.0f,
24055bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                                                   0.04045f, (1.0f / 12.92f), 0.0f);
24155bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2421b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
243600c737b64eae2c7379442ae2c852853cce3a278msarett                        case k2Dot2Curve_SkGammaNamed:
24455bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f);
24555bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2461b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
247600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kLinear_SkGammaNamed:
2481b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f);
2491b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2501b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2511b93bd1e6eba3d14593490e4e24a34546638c8damsarett                        default:
2521b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            SkASSERT(false);
2531b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2541b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    }
2551b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isValue(i)) {
2561b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize],
2571b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fValue);
2581b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2591b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isTable(i)) {
2601b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i),
2611b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fTable.fSize);
2621b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2631b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else {
2641b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    SkASSERT(gammas->isParametric(i));
265df44fc5f2bb282557df291e20dbd26c070533aa6Matt Sarett                    const SkColorSpaceTransferFn& params = gammas->params(i);
2661b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG,
2671b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fA, params.fB, params.fC, params.fD, params.fE,
2681b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fF);
2691b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett                }
2717bbda991af353fbe6b34132132d211d23a3dba8cmsarett            };
2727bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2737bbda991af353fbe6b34132132d211d23a3dba8cmsarett            if (gammasAreMatching) {
2747bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2757bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[1] = outGammaTables[0];
2767bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[2] = outGammaTables[0];
2777bbda991af353fbe6b34132132d211d23a3dba8cmsarett            } else {
2787bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2797bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(1);
2807bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(2);
2811b93bd1e6eba3d14593490e4e24a34546638c8damsarett            }
2827bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2837bbda991af353fbe6b34132132d211d23a3dba8cmsarett            break;
2841b93bd1e6eba3d14593490e4e24a34546638c8damsarett        }
2851b93bd1e6eba3d14593490e4e24a34546638c8damsarett    }
2861b93bd1e6eba3d14593490e4e24a34546638c8damsarett}
2871b93bd1e6eba3d14593490e4e24a34546638c8damsarett
288f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettvoid SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3],
2899488833428e83c93a7e6002f4d056084fb57112fraftias                                                 uint8_t* dstStorage,
2909488833428e83c93a7e6002f4d056084fb57112fraftias                                                 const SkColorSpace_XYZ* space,
291f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                                                 bool gammasAreMatching) {
292f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear,
293f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       gammasAreMatching);
294f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett}
295f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
2961b93bd1e6eba3d14593490e4e24a34546638c8damsarett///////////////////////////////////////////////////////////////////////////////////////////////////
2971b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2984be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace,
2994be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett                                                          SkColorSpace* dstSpace) {
3006006f678e78af7b6f67a454cd4bc213048983f9dmsarett    if (!srcSpace || !dstSpace) {
3016006f678e78af7b6f67a454cd4bc213048983f9dmsarett        // Invalid input
3026006f678e78af7b6f67a454cd4bc213048983f9dmsarett        return nullptr;
3036006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3046006f678e78af7b6f67a454cd4bc213048983f9dmsarett
3059488833428e83c93a7e6002f4d056084fb57112fraftias    if (SkColorSpace_Base::Type::kA2B == as_CSB(dstSpace)->type()) {
3062563601fc2b0505619f905f86bd249ae630197ccraftias        SkCSXformPrintf("A2B destinations not supported\n");
3079488833428e83c93a7e6002f4d056084fb57112fraftias        return nullptr;
3089488833428e83c93a7e6002f4d056084fb57112fraftias    }
3099488833428e83c93a7e6002f4d056084fb57112fraftias
3109488833428e83c93a7e6002f4d056084fb57112fraftias    if (SkColorSpace_Base::Type::kA2B == as_CSB(srcSpace)->type()) {
3112563601fc2b0505619f905f86bd249ae630197ccraftias        SkColorSpace_A2B* src = static_cast<SkColorSpace_A2B*>(srcSpace);
3122563601fc2b0505619f905f86bd249ae630197ccraftias        SkColorSpace_XYZ* dst = static_cast<SkColorSpace_XYZ*>(dstSpace);
3132563601fc2b0505619f905f86bd249ae630197ccraftias        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B(src, dst));
3149488833428e83c93a7e6002f4d056084fb57112fraftias    }
3159488833428e83c93a7e6002f4d056084fb57112fraftias    SkColorSpace_XYZ* srcSpaceXYZ = static_cast<SkColorSpace_XYZ*>(srcSpace);
3169488833428e83c93a7e6002f4d056084fb57112fraftias    SkColorSpace_XYZ* dstSpaceXYZ = static_cast<SkColorSpace_XYZ*>(dstSpace);
3179488833428e83c93a7e6002f4d056084fb57112fraftias
318200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    ColorSpaceMatch csm = kNone_ColorSpaceMatch;
3196006f678e78af7b6f67a454cd4bc213048983f9dmsarett    SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
3204be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett    if (SkColorSpace::Equals(srcSpace, dstSpace)) {
321200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        srcToDst.setIdentity();
322200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        csm = kFull_ColorSpaceMatch;
323971cd496b9e25f87f3a75a0015c203322907136abrianosman    } else {
324bbf251bf225489a0939fff6df938035a290f4d16Brian Osman        if (srcSpaceXYZ->toXYZD50Hash() == dstSpaceXYZ->toXYZD50Hash()) {
325bbf251bf225489a0939fff6df938035a290f4d16Brian Osman            SkASSERT(*srcSpaceXYZ->toXYZD50() == *dstSpaceXYZ->toXYZD50() && "Hash collision");
326971cd496b9e25f87f3a75a0015c203322907136abrianosman            srcToDst.setIdentity();
327971cd496b9e25f87f3a75a0015c203322907136abrianosman            csm = kGamut_ColorSpaceMatch;
328bbf251bf225489a0939fff6df938035a290f4d16Brian Osman        } else {
329bbf251bf225489a0939fff6df938035a290f4d16Brian Osman            srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50());
330971cd496b9e25f87f3a75a0015c203322907136abrianosman        }
3316006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3326006f678e78af7b6f67a454cd4bc213048983f9dmsarett
333f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kUseRasterPipeline) {
334f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        SrcGamma srcGamma = srcSpaceXYZ->gammaIsLinear() ? kLinear_SrcGamma : kTable_SrcGamma;
335f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        DstGamma dstGamma;
336f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        switch (dstSpaceXYZ->gammaNamed()) {
337f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            case kSRGB_SkGammaNamed:
338f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                dstGamma = kSRGB_DstGamma;
339f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                break;
340f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            case k2Dot2Curve_SkGammaNamed:
341f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                dstGamma = k2Dot2_DstGamma;
342f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                break;
343f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            case kLinear_SkGammaNamed:
344f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                dstGamma = kLinear_DstGamma;
345f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                break;
346f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            default:
347f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                dstGamma = kTable_DstGamma;
348f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                break;
349f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        }
350f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Pipeline(
351f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                srcSpaceXYZ, srcToDst, dstSpaceXYZ, csm, srcGamma, dstGamma));
352f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
353f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
354200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    switch (csm) {
355200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kNone_ColorSpaceMatch:
3569488833428e83c93a7e6002f4d056084fb57112fraftias            switch (dstSpaceXYZ->gammaNamed()) {
357600c737b64eae2c7379442ae2c852853cce3a278msarett                case kSRGB_SkGammaNamed:
3589488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
359f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3608bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
3619488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3628bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
363f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch>
3659488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
367600c737b64eae2c7379442ae2c852853cce3a278msarett                case k2Dot2Curve_SkGammaNamed:
3689488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
369f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
3719488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3728bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
373f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3748bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch>
3759488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3768bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
3778bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_SkGammaNamed:
3789488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
379f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
3819488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3828bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
383f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch>
3859488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
387200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett                default:
3889488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
389f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3908bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
3919488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
393f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
3948bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
3959488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
3968bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
397200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            }
398200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kGamut_ColorSpaceMatch:
3999488833428e83c93a7e6002f4d056084fb57112fraftias            switch (dstSpaceXYZ->gammaNamed()) {
400600c737b64eae2c7379442ae2c852853cce3a278msarett                case kSRGB_SkGammaNamed:
4019488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
402f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
4049488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
406f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4078bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch>
4089488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4098bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
410600c737b64eae2c7379442ae2c852853cce3a278msarett                case k2Dot2Curve_SkGammaNamed:
4119488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
412f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
4149488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4158bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
416f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4178bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch>
4189488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
4208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_SkGammaNamed:
4219488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
422f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
4249488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
426f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch>
4289488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
430200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett                default:
4319488833428e83c93a7e6002f4d056084fb57112fraftias                    if (srcSpaceXYZ->gammaIsLinear()) {
432f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kLinear_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
4349488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    } else {
436f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                                <kTable_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch>
4389488833428e83c93a7e6002f4d056084fb57112fraftias                                (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    }
440200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            }
441200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kFull_ColorSpaceMatch:
4429488833428e83c93a7e6002f4d056084fb57112fraftias            switch (dstSpaceXYZ->gammaNamed()) {
443600c737b64eae2c7379442ae2c852853cce3a278msarett                case kSRGB_SkGammaNamed:
444f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                            <kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMatch>
4469488833428e83c93a7e6002f4d056084fb57112fraftias                            (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
447600c737b64eae2c7379442ae2c852853cce3a278msarett                case k2Dot2Curve_SkGammaNamed:
448f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                            <kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceMatch>
4509488833428e83c93a7e6002f4d056084fb57112fraftias                            (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
4518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_SkGammaNamed:
452f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4538bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                            <kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpaceMatch>
4549488833428e83c93a7e6002f4d056084fb57112fraftias                            (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
455200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett                default:
456f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
4578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                            <kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceMatch>
4589488833428e83c93a7e6002f4d056084fb57112fraftias                            (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
459200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            }
4603418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        default:
461200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            SkASSERT(false);
462200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            return nullptr;
4636006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
4646006f678e78af7b6f67a454cd4bc213048983f9dmsarett}
4656006f678e78af7b6f67a454cd4bc213048983f9dmsarett
4666006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
4676006f678e78af7b6f67a454cd4bc213048983f9dmsarett
468df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett#define AI SK_ALWAYS_INLINE
469df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett
470df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_matrix(const float matrix[16],
471df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& rTgTbT) {
472200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rXgXbX = Sk4f::Load(matrix +  0);
473200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rYgYbY = Sk4f::Load(matrix +  4);
474200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rZgZbZ = Sk4f::Load(matrix +  8);
475200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rTgTbT = Sk4f::Load(matrix + 12);
476200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
477200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
478cf7b877d62537672b67449bc96858cc1262be5f8msarettenum Order {
479cf7b877d62537672b67449bc96858cc1262be5f8msarett    kRGBA_Order,
480cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_Order,
481cf7b877d62537672b67449bc96858cc1262be5f8msarett};
482cf7b877d62537672b67449bc96858cc1262be5f8msarett
483df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void set_rb_shifts(Order kOrder, int* kRShift, int* kBShift) {
484cf7b877d62537672b67449bc96858cc1262be5f8msarett    if (kRGBA_Order == kOrder) {
485cf7b877d62537672b67449bc96858cc1262be5f8msarett        *kRShift = 0;
486cf7b877d62537672b67449bc96858cc1262be5f8msarett        *kBShift = 16;
487cf7b877d62537672b67449bc96858cc1262be5f8msarett    } else {
488cf7b877d62537672b67449bc96858cc1262be5f8msarett        *kRShift = 16;
489cf7b877d62537672b67449bc96858cc1262be5f8msarett        *kBShift = 0;
490cf7b877d62537672b67449bc96858cc1262be5f8msarett    }
491cf7b877d62537672b67449bc96858cc1262be5f8msarett}
492cf7b877d62537672b67449bc96858cc1262be5f8msarett
493cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
494df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgb_from_tables(const uint32_t* src,
495df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                    Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
496df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                    const float* const srcTables[3]) {
497cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
498cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
499cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = { srcTables[0][(src[0] >> kRShift) & 0xFF],
500cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[1] >> kRShift) & 0xFF],
501cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[2] >> kRShift) & 0xFF],
502cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[3] >> kRShift) & 0xFF], };
503cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = { srcTables[1][(src[0] >> kGShift) & 0xFF],
504cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[1] >> kGShift) & 0xFF],
505cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[2] >> kGShift) & 0xFF],
506cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[3] >> kGShift) & 0xFF], };
507cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = { srcTables[2][(src[0] >> kBShift) & 0xFF],
508cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[1] >> kBShift) & 0xFF],
509cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[2] >> kBShift) & 0xFF],
510cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[3] >> kBShift) & 0xFF], };
511200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    a = 0.0f; // Don't let the compiler complain that |a| is uninitialized.
512200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
513200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
514cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
515df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgba_from_tables(const uint32_t* src,
516df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                     Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
517df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                     const float* const srcTables[3]) {
518cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
519cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
520cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = { srcTables[0][(src[0] >> kRShift) & 0xFF],
521cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[1] >> kRShift) & 0xFF],
522cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[2] >> kRShift) & 0xFF],
523cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[0][(src[3] >> kRShift) & 0xFF], };
5245414be06935ce0f990a2df5dccaf9ddec78ec553msarett    g = { srcTables[1][(src[0] >> kGShift) & 0xFF],
525cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[1] >> kGShift) & 0xFF],
526cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[2] >> kGShift) & 0xFF],
527cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[1][(src[3] >> kGShift) & 0xFF], };
528cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = { srcTables[2][(src[0] >> kBShift) & 0xFF],
529cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[1] >> kBShift) & 0xFF],
530cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[2] >> kBShift) & 0xFF],
531cf7b877d62537672b67449bc96858cc1262be5f8msarett          srcTables[2][(src[3] >> kBShift) & 0xFF], };
532200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    a = (1.0f / 255.0f) * SkNx_cast<float>(Sk4u::Load(src) >> 24);
533200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
534200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
535cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
5362563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void load_rgb_linear(const uint32_t* src, Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
537df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               const float* const[3]) {
538cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
539cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
540cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF);
541cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF);
542cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF);
543be362774f9b9e8964544a579281603ed995e6e5amsarett    a = 0.0f; // Don't let the compiler complain that |a| is uninitialized.
5448bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
5458bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
546cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
5472563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void load_rgba_linear(const uint32_t* src, Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
548df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                const float* const[3]) {
549cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
550cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
551cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF);
552cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF);
553cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF);
554cf7b877d62537672b67449bc96858cc1262be5f8msarett    a = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 24));
5558bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
5568bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
557cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
558df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgb_from_tables_1(const uint32_t* src,
559df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                      Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
560df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                      const float* const srcTables[3]) {
561cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
562cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
563cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]);
564cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]);
565cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]);
566a9f64dec63b6f4169ba16f8b6c63fff5a6494029Matt Sarett    a = 0.0f; // Don't let MSAN complain that |a| is uninitialized.
567200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
568200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
569cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
570df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgba_from_tables_1(const uint32_t* src,
571df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                       Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
572df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                       const float* const srcTables[3]) {
573cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
574cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
575cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]);
576cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]);
577cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]);
578200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    a = (1.0f / 255.0f) * Sk4f(*src >> 24);
579200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
580200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
581cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
582df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgb_linear_1(const uint32_t* src,
583df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                 Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
584df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                 const float* const srcTables[3]) {
585cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
586cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
587cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF));
588cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF));
589cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF));
590a9f64dec63b6f4169ba16f8b6c63fff5a6494029Matt Sarett    a = 0.0f; // Don't let MSAN complain that |a| is uninitialized.
5918bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
5928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
593cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
594df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void load_rgba_linear_1(const uint32_t* src,
595df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                  Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a,
596df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                  const float* const srcTables[3]) {
597cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
598cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
599cf7b877d62537672b67449bc96858cc1262be5f8msarett    r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF));
600cf7b877d62537672b67449bc96858cc1262be5f8msarett    g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF));
601cf7b877d62537672b67449bc96858cc1262be5f8msarett    b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF));
602cf7b877d62537672b67449bc96858cc1262be5f8msarett    a = Sk4f((1.0f / 255.0f) * ((*src >> 24)));
6038bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
6048bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
605df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void transform_gamut(const Sk4f& r, const Sk4f& g, const Sk4f& b, const Sk4f& a,
606df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ,
607df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da) {
608200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dr = rXgXbX[0]*r + rYgYbY[0]*g + rZgZbZ[0]*b;
609200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dg = rXgXbX[1]*r + rYgYbY[1]*g + rZgZbZ[1]*b;
610200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    db = rXgXbX[2]*r + rYgYbY[2]*g + rZgZbZ[2]*b;
611200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    da = a;
612200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
613200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
614df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void transform_gamut_1(const Sk4f& r, const Sk4f& g, const Sk4f& b,
615df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                 const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ,
616df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                 Sk4f& rgba) {
617200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba = rXgXbX*r + rYgYbY*g + rZgZbZ*b;
618200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
619200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
620df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void translate_gamut(const Sk4f& rTgTbT, Sk4f& dr, Sk4f& dg, Sk4f& db) {
621200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dr = dr + rTgTbT[0];
622200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dg = dg + rTgTbT[1];
623200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    db = db + rTgTbT[2];
624200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
625200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
626df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void translate_gamut_1(const Sk4f& rTgTbT, Sk4f& rgba) {
627200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba = rgba + rTgTbT;
628200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
629200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
630df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da) {
631200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dr = da * dr;
632200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dg = da * dg;
633200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    db = da * db;
634200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
635200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
636df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void premultiply_1(const Sk4f& a, Sk4f& rgba) {
637200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba = a * rgba;
638200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
639200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
640cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
6412563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_srgb(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&,
642df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                          const uint8_t* const[3]) {
643cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
644cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
645200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dr = sk_linear_to_srgb_needs_trunc(dr);
646200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dg = sk_linear_to_srgb_needs_trunc(dg);
647200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    db = sk_linear_to_srgb_needs_trunc(db);
648200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
64917e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dr = sk_clamp_0_255(dr);
65017e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dg = sk_clamp_0_255(dg);
65117e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    db = sk_clamp_0_255(db);
65217e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett
653200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i da = Sk4i::Load(src) & 0xFF000000;
654200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
655200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i rgba = (SkNx_cast<int>(dr) << kRShift)
656200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (SkNx_cast<int>(dg) << kGShift)
657200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (SkNx_cast<int>(db) << kBShift)
658200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (da                           );
659200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba.store(dst);
660200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
661200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
662cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
663df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_srgb_1(void* dst, const uint32_t* src,
664df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                            Sk4f& rgba, const Sk4f&,
665df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                            const uint8_t* const[3]) {
66617e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba));
667200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
668200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    uint32_t tmp;
669200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp);
670200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF);
671cf7b877d62537672b67449bc96858cc1262be5f8msarett    if (kBGRA_Order == kOrder) {
672200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        tmp = SkSwizzle_RB(tmp);
673200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    }
674200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
675200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    *(uint32_t*)dst = tmp;
676200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
677200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
678df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI Sk4f linear_to_2dot2(const Sk4f& x) {
679200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    // x^(29/64) is a very good approximation of the true value, x^(1/2.2).
680200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    auto x2  = x.rsqrt(),                            // x^(-1/2)
681200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett         x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(),   // x^(-1/32)
682200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett         x64 = x32.rsqrt();                          // x^(+1/64)
683200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
684200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    // 29 = 32 - 2 - 1
685200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    return 255.0f * x2.invert() * x32 * x64.invert();
686200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
687200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
688cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
6892563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_2dot2(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&,
690df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           const uint8_t* const[3]) {
691cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
692cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
693200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dr = linear_to_2dot2(dr);
694200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dg = linear_to_2dot2(dg);
695200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    db = linear_to_2dot2(db);
696200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
69717e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dr = sk_clamp_0_255(dr);
69817e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dg = sk_clamp_0_255(dg);
69917e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    db = sk_clamp_0_255(db);
70017e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett
701200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i da = Sk4i::Load(src) & 0xFF000000;
702200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
703200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i rgba = (Sk4f_round(dr) << kRShift)
704200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (Sk4f_round(dg) << kGShift)
705200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (Sk4f_round(db) << kBShift)
706200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett              | (da                       );
707200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba.store(dst);
708200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
709200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
710cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
711df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_2dot2_1(void* dst, const uint32_t* src,
712df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                             Sk4f& rgba, const Sk4f&,
713df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                             const uint8_t* const[3]) {
71417e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    rgba = sk_clamp_0_255(linear_to_2dot2(rgba));
715200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
716200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    uint32_t tmp;
717200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp);
718200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF);
719cf7b877d62537672b67449bc96858cc1262be5f8msarett    if (kBGRA_Order == kOrder) {
720200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        tmp = SkSwizzle_RB(tmp);
721200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    }
722200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
723200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    *(uint32_t*)dst = tmp;
724200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
725200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
726cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
7272563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_linear(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&,
728df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                            const uint8_t* const[3]) {
729cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
730cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
73117e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dr = sk_clamp_0_255(255.0f * dr);
73217e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dg = sk_clamp_0_255(255.0f * dg);
73317e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    db = sk_clamp_0_255(255.0f * db);
7348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
7358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    Sk4i da = Sk4i::Load(src) & 0xFF000000;
7368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
7378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    Sk4i rgba = (Sk4f_round(dr) << kRShift)
7388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett              | (Sk4f_round(dg) << kGShift)
7398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett              | (Sk4f_round(db) << kBShift)
7408bbcd5aab81dc0742c3367479c0c9d97363b1203msarett              | (da                       );
7418bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    rgba.store(dst);
7428bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
7438bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
744cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
745df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_linear_1(void* dst, const uint32_t* src,
746df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                              Sk4f& rgba, const Sk4f&,
747df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                              const uint8_t* const[3]) {
74817e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    rgba = sk_clamp_0_255(255.0f * rgba);
7498bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
7508bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    uint32_t tmp;
7518bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp);
7528bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF);
753cf7b877d62537672b67449bc96858cc1262be5f8msarett    if (kBGRA_Order == kOrder) {
7548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        tmp = SkSwizzle_RB(tmp);
7558bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    }
7568bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
7578bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    *(uint32_t*)dst = tmp;
7588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
7598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
760cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
7612563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_f16(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da,
7622563601fc2b0505619f905f86bd249ae630197ccraftias                         const uint8_t* const[3]) {
76333cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein    Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr),
76433cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SkFloatToHalf_finite_ftz(dg),
76533cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SkFloatToHalf_finite_ftz(db),
76633cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SkFloatToHalf_finite_ftz(da));
767200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
768200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
769cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
770df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_f16_1(void* dst, const uint32_t* src,
771df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           Sk4f& rgba, const Sk4f& a,
772df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           const uint8_t* const[3]) {
773200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]);
7748ae991e433d2c0814ea5579613f00173805ff057mtklein    SkFloatToHalf_finite_ftz(rgba).store((uint64_t*) dst);
775200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
776200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
777cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
7782563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_f32(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da,
779df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                         const uint8_t* const[3]) {
78033cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein    Sk4f::Store4(dst, dr, dg, db, da);
781c0444615ed76360f680619ad4d1f92cda6181a50msarett}
782c0444615ed76360f680619ad4d1f92cda6181a50msarett
783cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
784df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_f32_1(void* dst, const uint32_t* src,
785df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           Sk4f& rgba, const Sk4f& a,
786df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                           const uint8_t* const[3]) {
787c0444615ed76360f680619ad4d1f92cda6181a50msarett    rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]);
788c0444615ed76360f680619ad4d1f92cda6181a50msarett    rgba.store((float*) dst);
789c0444615ed76360f680619ad4d1f92cda6181a50msarett}
790c0444615ed76360f680619ad4d1f92cda6181a50msarett
791cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
7922563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_f16_opaque(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db,
7932563601fc2b0505619f905f86bd249ae630197ccraftias                                Sk4f&, const uint8_t* const[3]) {
79433cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein    Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr),
79533cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SkFloatToHalf_finite_ftz(dg),
79633cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SkFloatToHalf_finite_ftz(db),
79733cbfd75afdd383770bb6253c06ba819a2481a35Mike Klein                      SK_Half1);
798200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
799200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
800cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
801df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_f16_1_opaque(void* dst, const uint32_t* src,
802df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                  Sk4f& rgba, const Sk4f&,
803df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                                  const uint8_t* const[3]) {
804200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    uint64_t tmp;
8058ae991e433d2c0814ea5579613f00173805ff057mtklein    SkFloatToHalf_finite_ftz(rgba).store(&tmp);
806200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    tmp |= static_cast<uint64_t>(SK_Half1) << 48;
807200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    *((uint64_t*) dst) = tmp;
808200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
809200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
810cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
8112563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI void store_generic(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&,
8122563601fc2b0505619f905f86bd249ae630197ccraftias                             const uint8_t* const dstTables[3]) {
813cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
814cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
81517e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f);
81617e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f);
81717e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f);
818200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
819200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i ir = Sk4f_round(dr);
820200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i ig = Sk4f_round(dg);
821200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i ib = Sk4f_round(db);
822200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
823200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i da = Sk4i::Load(src) & 0xFF000000;
824200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
825200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    uint32_t* dst32 = (uint32_t*) dst;
826200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dst32[0] = dstTables[0][ir[0]] << kRShift
827200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[1][ig[0]] << kGShift
828200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[2][ib[0]] << kBShift
829200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | da[0];
830200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dst32[1] = dstTables[0][ir[1]] << kRShift
831200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[1][ig[1]] << kGShift
832200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[2][ib[1]] << kBShift
833200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | da[1];
834200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dst32[2] = dstTables[0][ir[2]] << kRShift
835200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[1][ig[2]] << kGShift
836200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[2][ib[2]] << kBShift
837200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | da[2];
838200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    dst32[3] = dstTables[0][ir[3]] << kRShift
839200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[1][ig[3]] << kGShift
840200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | dstTables[2][ib[3]] << kBShift
841200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett             | da[3];
842200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
843200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
844cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <Order kOrder>
845df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI void store_generic_1(void* dst, const uint32_t* src,
846df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               Sk4f& rgba, const Sk4f&,
847df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               const uint8_t* const dstTables[3]) {
848cf7b877d62537672b67449bc96858cc1262be5f8msarett    int kRShift, kGShift = 8, kBShift;
849cf7b877d62537672b67449bc96858cc1262be5f8msarett    set_rb_shifts(kOrder, &kRShift, &kBShift);
85017e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett    rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f);
851200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
852200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    Sk4i indices = Sk4f_round(rgba);
853200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
8549dc6cf6b8833d36c29a23d2519989b069745fcd5msarett    *((uint32_t*) dst) = dstTables[0][indices[0]] << kRShift
8559dc6cf6b8833d36c29a23d2519989b069745fcd5msarett                       | dstTables[1][indices[1]] << kGShift
8569dc6cf6b8833d36c29a23d2519989b069745fcd5msarett                       | dstTables[2][indices[2]] << kBShift
857200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett                       | (*src & 0xFF000000);
858200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett}
859200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
860cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(load_rgb_from_tables<kRGBA_Order>  )* LoadFn;
861cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(load_rgb_from_tables_1<kRGBA_Order>)* Load1Fn;
862cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(store_generic<kRGBA_Order>         )* StoreFn;
863cf7b877d62537672b67449bc96858cc1262be5f8msaretttypedef decltype(store_generic_1<kRGBA_Order>       )* Store1Fn;
8648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
8658bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum SrcFormat {
8668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    kRGBA_8888_Linear_SrcFormat,
8678bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    kRGBA_8888_Table_SrcFormat,
868cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_Linear_SrcFormat,
869cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_Table_SrcFormat,
8708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett};
8718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
8728bbcd5aab81dc0742c3367479c0c9d97363b1203msarettenum DstFormat {
873cf7b877d62537672b67449bc96858cc1262be5f8msarett    kRGBA_8888_Linear_DstFormat,
874cf7b877d62537672b67449bc96858cc1262be5f8msarett    kRGBA_8888_SRGB_DstFormat,
875cf7b877d62537672b67449bc96858cc1262be5f8msarett    kRGBA_8888_2Dot2_DstFormat,
876cf7b877d62537672b67449bc96858cc1262be5f8msarett    kRGBA_8888_Table_DstFormat,
877cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_Linear_DstFormat,
878cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_SRGB_DstFormat,
879cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_2Dot2_DstFormat,
880cf7b877d62537672b67449bc96858cc1262be5f8msarett    kBGRA_8888_Table_DstFormat,
8818bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    kF16_Linear_DstFormat,
882c0444615ed76360f680619ad4d1f92cda6181a50msarett    kF32_Linear_DstFormat,
8838bbcd5aab81dc0742c3367479c0c9d97363b1203msarett};
8848bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
8858bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcFormat kSrc,
8868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett          DstFormat kDst,
8878bbcd5aab81dc0742c3367479c0c9d97363b1203msarett          SkAlphaType kAlphaType,
888cf7b877d62537672b67449bc96858cc1262be5f8msarett          ColorSpaceMatch kCSM>
8895934646b4937a05d5e8297448ea6613a89f8903aMatt Sarettstatic void color_xform_RGBA(void* dst, const void* vsrc, int len,
8905934646b4937a05d5e8297448ea6613a89f8903aMatt Sarett                             const float* const srcTables[3], const float matrix[16],
8915934646b4937a05d5e8297448ea6613a89f8903aMatt Sarett                             const uint8_t* const dstTables[3]) {
8928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    LoadFn load;
8938bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    Load1Fn load_1;
894c0444615ed76360f680619ad4d1f92cda6181a50msarett    static constexpr bool loadAlpha = (kPremul_SkAlphaType == kAlphaType) ||
895c0444615ed76360f680619ad4d1f92cda6181a50msarett                                      (kF16_Linear_DstFormat == kDst) ||
896c0444615ed76360f680619ad4d1f92cda6181a50msarett                                      (kF32_Linear_DstFormat == kDst);
8978bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    switch (kSrc) {
8988bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kRGBA_8888_Linear_SrcFormat:
899c0444615ed76360f680619ad4d1f92cda6181a50msarett            if (loadAlpha) {
900cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgba_linear<kRGBA_Order>;
901cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgba_linear_1<kRGBA_Order>;
9028bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            } else {
903cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgb_linear<kRGBA_Order>;
904cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgb_linear_1<kRGBA_Order>;
9058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            }
9068bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
9078bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kRGBA_8888_Table_SrcFormat:
908c0444615ed76360f680619ad4d1f92cda6181a50msarett            if (loadAlpha) {
909cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgba_from_tables<kRGBA_Order>;
910cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgba_from_tables_1<kRGBA_Order>;
9118bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            } else {
912cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgb_from_tables<kRGBA_Order>;
913cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgb_from_tables_1<kRGBA_Order>;
914cf7b877d62537672b67449bc96858cc1262be5f8msarett            }
915cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
916cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_Linear_SrcFormat:
917cf7b877d62537672b67449bc96858cc1262be5f8msarett            if (loadAlpha) {
918cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgba_linear<kBGRA_Order>;
919cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgba_linear_1<kBGRA_Order>;
920cf7b877d62537672b67449bc96858cc1262be5f8msarett            } else {
921cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgb_linear<kBGRA_Order>;
922cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgb_linear_1<kBGRA_Order>;
923cf7b877d62537672b67449bc96858cc1262be5f8msarett            }
924cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
925cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_Table_SrcFormat:
926cf7b877d62537672b67449bc96858cc1262be5f8msarett            if (loadAlpha) {
927cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgba_from_tables<kBGRA_Order>;
928cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgba_from_tables_1<kBGRA_Order>;
929cf7b877d62537672b67449bc96858cc1262be5f8msarett            } else {
930cf7b877d62537672b67449bc96858cc1262be5f8msarett                load = load_rgb_from_tables<kBGRA_Order>;
931cf7b877d62537672b67449bc96858cc1262be5f8msarett                load_1 = load_rgb_from_tables_1<kBGRA_Order>;
9328bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            }
9338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
9348bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    }
9358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
9368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    StoreFn store;
9378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    Store1Fn store_1;
9388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    size_t sizeOfDstPixel;
9398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    switch (kDst) {
940cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kRGBA_8888_Linear_DstFormat:
941cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_linear<kRGBA_Order>;
942cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_linear_1<kRGBA_Order>;
943cf7b877d62537672b67449bc96858cc1262be5f8msarett            sizeOfDstPixel = 4;
944cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
945cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kRGBA_8888_SRGB_DstFormat:
946cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_srgb<kRGBA_Order>;
947cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_srgb_1<kRGBA_Order>;
948cf7b877d62537672b67449bc96858cc1262be5f8msarett            sizeOfDstPixel = 4;
949cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
950cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kRGBA_8888_2Dot2_DstFormat:
951cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_2dot2<kRGBA_Order>;
952cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_2dot2_1<kRGBA_Order>;
9538bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            sizeOfDstPixel = 4;
9548bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
955cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kRGBA_8888_Table_DstFormat:
956cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_generic<kRGBA_Order>;
957cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_generic_1<kRGBA_Order>;
9588bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            sizeOfDstPixel = 4;
9598bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
960cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_Linear_DstFormat:
961cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_linear<kBGRA_Order>;
962cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_linear_1<kBGRA_Order>;
9638bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            sizeOfDstPixel = 4;
9648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
965cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_SRGB_DstFormat:
966cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_srgb<kBGRA_Order>;
967cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_srgb_1<kBGRA_Order>;
968cf7b877d62537672b67449bc96858cc1262be5f8msarett            sizeOfDstPixel = 4;
969cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
970cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_2Dot2_DstFormat:
971cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_2dot2<kBGRA_Order>;
972cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_2dot2_1<kBGRA_Order>;
973cf7b877d62537672b67449bc96858cc1262be5f8msarett            sizeOfDstPixel = 4;
974cf7b877d62537672b67449bc96858cc1262be5f8msarett            break;
975cf7b877d62537672b67449bc96858cc1262be5f8msarett        case kBGRA_8888_Table_DstFormat:
976cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_generic<kBGRA_Order>;
977cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_generic_1<kBGRA_Order>;
9788bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            sizeOfDstPixel = 4;
9798bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
9808bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kF16_Linear_DstFormat:
981cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_opaque<kRGBA_Order> :
982cf7b877d62537672b67449bc96858cc1262be5f8msarett                                                            store_f16<kRGBA_Order>;
983cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_1_opaque<kRGBA_Order> :
984cf7b877d62537672b67449bc96858cc1262be5f8msarett                                                            store_f16_1<kRGBA_Order>;
9858bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            sizeOfDstPixel = 8;
9868bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            break;
987c0444615ed76360f680619ad4d1f92cda6181a50msarett        case kF32_Linear_DstFormat:
988cf7b877d62537672b67449bc96858cc1262be5f8msarett            store   = store_f32<kRGBA_Order>;
989cf7b877d62537672b67449bc96858cc1262be5f8msarett            store_1 = store_f32_1<kRGBA_Order>;
990c0444615ed76360f680619ad4d1f92cda6181a50msarett            sizeOfDstPixel = 16;
991c0444615ed76360f680619ad4d1f92cda6181a50msarett            break;
9928bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    }
9938bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
994d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    const uint32_t* src = (const uint32_t*) vsrc;
995d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT;
996d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT);
997d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
998d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    if (len >= 4) {
999d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        // Naively this would be a loop of load-transform-store, but we found it faster to
1000d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        // move the N+1th load ahead of the Nth store.  We don't bother doing this for N<4.
1001d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        Sk4f r, g, b, a;
1002d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        load(src, r, g, b, a, srcTables);
1003d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        src += 4;
1004d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        len -= 4;
1005d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1006d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        Sk4f dr, dg, db, da;
1007d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        while (len >= 4) {
1008d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            if (kNone_ColorSpaceMatch == kCSM) {
1009d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da);
1010d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                translate_gamut(rTgTbT, dr, dg, db);
1011d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            } else {
1012d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                dr = r;
1013d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                dg = g;
1014d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                db = b;
1015d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                da = a;
1016d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            }
1017d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1018d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            if (kPremul_SkAlphaType == kAlphaType) {
1019d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett                premultiply(dr, dg, db, da);
1020d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            }
1021d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1022d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            load(src, r, g, b, a, srcTables);
1023d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1024d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            store(dst, src - 4, dr, dg, db, da, dstTables);
1025d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel);
1026d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            src += 4;
1027d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            len -= 4;
1028d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        }
1029d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1030d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        if (kNone_ColorSpaceMatch == kCSM) {
1031d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da);
1032d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            translate_gamut(rTgTbT, dr, dg, db);
1033d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        } else {
1034d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            dr = r;
1035d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            dg = g;
1036d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            db = b;
1037d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            da = a;
1038d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        }
1039d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1040d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        if (kPremul_SkAlphaType == kAlphaType) {
1041d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            premultiply(dr, dg, db, da);
1042d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        }
1043d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1044d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        store(dst, src - 4, dr, dg, db, da, dstTables);
1045d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel);
1046d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    }
1047d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1048d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    while (len > 0) {
1049d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        Sk4f r, g, b, a;
1050d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        load_1(src, r, g, b, a, srcTables);
1051d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1052d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        Sk4f rgba;
1053d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        if (kNone_ColorSpaceMatch == kCSM) {
1054d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba);
1055d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            translate_gamut_1(rTgTbT, rgba);
1056d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        } else {
1057d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            rgba = Sk4f(r[0], g[0], b[0], a[0]);
1058d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        }
1059d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1060d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        if (kPremul_SkAlphaType == kAlphaType) {
1061d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett            premultiply_1(a, rgba);
1062d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        }
1063d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1064d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        store_1(dst, src, rgba, a, dstTables);
1065d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett
1066d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        src += 1;
1067d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        len -= 1;
1068d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett        dst = SkTAddOffset<void>(dst, sizeOfDstPixel);
1069d478a99f5c29f0e8fa64b50831f53232f5577f2dMatt Sarett    }
10708bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
10718bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
10723418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett///////////////////////////////////////////////////////////////////////////////////////////////////
10730f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett
10742563601fc2b0505619f905f86bd249ae630197ccraftiasstatic AI int num_tables(SkColorSpace_XYZ* space) {
10759488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
10767bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kSRGB_SkGammaNamed:
10777bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case k2Dot2Curve_SkGammaNamed:
10787bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kLinear_SkGammaNamed:
10797bbda991af353fbe6b34132132d211d23a3dba8cmsarett            return 0;
10807bbda991af353fbe6b34132132d211d23a3dba8cmsarett        default: {
10819488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
10827bbda991af353fbe6b34132132d211d23a3dba8cmsarett            SkASSERT(gammas);
10837bbda991af353fbe6b34132132d211d23a3dba8cmsarett
10847bbda991af353fbe6b34132132d211d23a3dba8cmsarett            bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) &&
10857bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->data(0) == gammas->data(1)) &&
10867bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->type(0) == gammas->type(2)) &&
10877bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->data(0) == gammas->data(2));
10887bbda991af353fbe6b34132132d211d23a3dba8cmsarett
10897bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // It's likely that each component will have the same gamma.  In this case,
10907bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // we only need to build one table.
10917bbda991af353fbe6b34132132d211d23a3dba8cmsarett            return gammasAreMatching ? 1 : 3;
10927bbda991af353fbe6b34132132d211d23a3dba8cmsarett        }
10937bbda991af353fbe6b34132132d211d23a3dba8cmsarett    }
10947bbda991af353fbe6b34132132d211d23a3dba8cmsarett}
10957bbda991af353fbe6b34132132d211d23a3dba8cmsarett
10968bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
1097f489886915034093278353d06c6f1973b2e8b7d2Matt SarettSkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
10989488833428e83c93a7e6002f4d056084fb57112fraftias::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
10999488833428e83c93a7e6002f4d056084fb57112fraftias                        SkColorSpace_XYZ* dstSpace)
11003418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{
1101de68d6c4616d86621373d88100002ddfdb9c08e3brianosman    srcToDst.asColMajorf(fSrcToDst);
11027bbda991af353fbe6b34132132d211d23a3dba8cmsarett
11034be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett    const int numSrcTables = num_tables(srcSpace);
1104f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    const size_t srcEntries = numSrcTables * 256;
11057bbda991af353fbe6b34132132d211d23a3dba8cmsarett    const bool srcGammasAreMatching = (1 >= numSrcTables);
1106f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    fSrcStorage.reset(srcEntries);
1107f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear,
1108f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       srcGammasAreMatching);
1109f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
1110f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    const int numDstTables = num_tables(dstSpace);
11119488833428e83c93a7e6002f4d056084fb57112fraftias    dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
11123418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett}
1113dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
11147bbda991af353fbe6b34132132d211d23a3dba8cmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
11157bbda991af353fbe6b34132132d211d23a3dba8cmsarett
1116cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
1117df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaType alphaType,
1118df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               const float* const srcTables[3], const float matrix[16],
1119df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                               const uint8_t* const dstTables[3]) {
11208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    switch (alphaType) {
11218bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kOpaque_SkAlphaType:
112231d097e865f266c8398f45114e4c75c0dfdef058msarett            color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM>
11238bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    (dst, src, len, srcTables, matrix, dstTables);
112431d097e865f266c8398f45114e4c75c0dfdef058msarett            return true;
11258bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kPremul_SkAlphaType:
112631d097e865f266c8398f45114e4c75c0dfdef058msarett            color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM>
11278bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    (dst, src, len, srcTables, matrix, dstTables);
112831d097e865f266c8398f45114e4c75c0dfdef058msarett            return true;
11298bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        case kUnpremul_SkAlphaType:
113031d097e865f266c8398f45114e4c75c0dfdef058msarett            color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM>
11318bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                    (dst, src, len, srcTables, matrix, dstTables);
113231d097e865f266c8398f45114e4c75c0dfdef058msarett            return true;
11338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett        default:
113431d097e865f266c8398f45114e4c75c0dfdef058msarett            return false;
11358bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    }
11368bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
11378bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
1138cf7b877d62537672b67449bc96858cc1262be5f8msaretttemplate <SrcGamma kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
1139df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarettstatic AI bool apply_set_src(void* dst, const void* src, int len, SkAlphaType alphaType,
1140df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                             const float* const srcTables[3], const float matrix[16],
1141df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                             const uint8_t* const dstTables[3],
1142df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett                             SkColorSpaceXform::ColorFormat srcColorFormat) {
1143cf7b877d62537672b67449bc96858cc1262be5f8msarett    switch (srcColorFormat) {
1144cf7b877d62537672b67449bc96858cc1262be5f8msarett        case SkColorSpaceXform::kRGBA_8888_ColorFormat:
1145cf7b877d62537672b67449bc96858cc1262be5f8msarett            switch (kSrc) {
1146cf7b877d62537672b67449bc96858cc1262be5f8msarett                case kLinear_SrcGamma:
1147cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_alpha<kRGBA_8888_Linear_SrcFormat, kDst, kCSM>
1148cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, nullptr, matrix, dstTables);
1149cf7b877d62537672b67449bc96858cc1262be5f8msarett                case kTable_SrcGamma:
1150cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_alpha<kRGBA_8888_Table_SrcFormat, kDst, kCSM>
1151cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, srcTables, matrix, dstTables);
1152cf7b877d62537672b67449bc96858cc1262be5f8msarett            }
1153cf7b877d62537672b67449bc96858cc1262be5f8msarett        case SkColorSpaceXform::kBGRA_8888_ColorFormat:
1154cf7b877d62537672b67449bc96858cc1262be5f8msarett            switch (kSrc) {
1155cf7b877d62537672b67449bc96858cc1262be5f8msarett                case kLinear_SrcGamma:
1156cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_alpha<kBGRA_8888_Linear_SrcFormat, kDst, kCSM>
1157cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, nullptr, matrix, dstTables);
1158cf7b877d62537672b67449bc96858cc1262be5f8msarett                case kTable_SrcGamma:
1159cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_alpha<kBGRA_8888_Table_SrcFormat, kDst, kCSM>
1160cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, srcTables, matrix, dstTables);
1161cf7b877d62537672b67449bc96858cc1262be5f8msarett            }
1162cf7b877d62537672b67449bc96858cc1262be5f8msarett        default:
116331d097e865f266c8398f45114e4c75c0dfdef058msarett            return false;
11648bbcd5aab81dc0742c3367479c0c9d97363b1203msarett    }
11658bbcd5aab81dc0742c3367479c0c9d97363b1203msarett}
11668bbcd5aab81dc0742c3367479c0c9d97363b1203msarett
1167df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett#undef AI
1168df303a6f59a2121c133738d6304d2476689a4fd9Matt Sarett
11698bbcd5aab81dc0742c3367479c0c9d97363b1203msaretttemplate <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
1170f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettbool SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
117131d097e865f266c8398f45114e4c75c0dfdef058msarett::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src,
117231d097e865f266c8398f45114e4c75c0dfdef058msarett          int len, SkAlphaType alphaType) const
11733418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{
1174200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    if (kFull_ColorSpaceMatch == kCSM) {
117517e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett        switch (alphaType) {
117617e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett            case kPremul_SkAlphaType:
117717e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                // We can't skip the xform since we need to perform a premultiply in the
117817e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                // linear space.
117917e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                break;
118017e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett            default:
118117e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                switch (dstColorFormat) {
118217e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                    case kRGBA_8888_ColorFormat:
118317e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        memcpy(dst, src, len * sizeof(uint32_t));
118417e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        return true;
118517e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                    case kBGRA_8888_ColorFormat:
118617e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
118717e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        return true;
118817e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                    case kRGBA_F16_ColorFormat:
118917e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                    case kRGBA_F32_ColorFormat:
119017e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        // There's still work to do to xform to linear floats.
119117e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        break;
119217e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                    default:
119317e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                        return false;
119417e494070ab1c76b2e5e4c0780b7a83c737dd84cMatt Sarett                }
1195200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        }
1196200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    }
1197200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett
1198c0444615ed76360f680619ad4d1f92cda6181a50msarett    switch (dstColorFormat) {
1199c0444615ed76360f680619ad4d1f92cda6181a50msarett        case kRGBA_8888_ColorFormat:
12008bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            switch (kDst) {
12018bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_DstGamma:
1202cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kRGBA_8888_Linear_DstFormat, kCSM>
1203cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1204cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12058bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kSRGB_DstGamma:
1206cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kRGBA_8888_SRGB_DstFormat, kCSM>
1207cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1208cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12098bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case k2Dot2_DstGamma:
1210cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kRGBA_8888_2Dot2_DstFormat, kCSM>
1211cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1212cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12138bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kTable_DstGamma:
1214cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kRGBA_8888_Table_DstFormat, kCSM>
1215cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables,
1216cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
1217d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett            }
1218c0444615ed76360f680619ad4d1f92cda6181a50msarett        case kBGRA_8888_ColorFormat:
12198bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            switch (kDst) {
12208bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_DstGamma:
1221cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kBGRA_8888_Linear_DstFormat, kCSM>
1222cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1223cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kSRGB_DstGamma:
1225cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kBGRA_8888_SRGB_DstFormat, kCSM>
1226cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1227cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12288bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case k2Dot2_DstGamma:
1229cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kBGRA_8888_2Dot2_DstFormat, kCSM>
1230cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1231cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
12328bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kTable_DstGamma:
1233cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kBGRA_8888_Table_DstFormat, kCSM>
1234cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables,
1235cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
1236d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett            }
1237c0444615ed76360f680619ad4d1f92cda6181a50msarett        case kRGBA_F16_ColorFormat:
12388bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            switch (kDst) {
12398bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                case kLinear_DstGamma:
1240cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kF16_Linear_DstFormat, kCSM>
1241cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1242cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
1243d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett                default:
124431d097e865f266c8398f45114e4c75c0dfdef058msarett                    return false;
1245d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett            }
1246c0444615ed76360f680619ad4d1f92cda6181a50msarett        case kRGBA_F32_ColorFormat:
1247c0444615ed76360f680619ad4d1f92cda6181a50msarett            switch (kDst) {
1248c0444615ed76360f680619ad4d1f92cda6181a50msarett                case kLinear_DstGamma:
1249cf7b877d62537672b67449bc96858cc1262be5f8msarett                    return apply_set_src<kSrc, kF32_Linear_DstFormat, kCSM>
1250cf7b877d62537672b67449bc96858cc1262be5f8msarett                            (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr,
1251cf7b877d62537672b67449bc96858cc1262be5f8msarett                             srcColorFormat);
1252c0444615ed76360f680619ad4d1f92cda6181a50msarett                default:
125331d097e865f266c8398f45114e4c75c0dfdef058msarett                    return false;
1254c0444615ed76360f680619ad4d1f92cda6181a50msarett            }
1255d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett        default:
125631d097e865f266c8398f45114e4c75c0dfdef058msarett            return false;
1257d1ec89b1aca8f37a460a425259a23275f4d9a81dmsarett    }
12589ce3a543c92a73e6daca420defc042886b3f2019msarett}
12599dc6cf6b8833d36c29a23d2519989b069745fcd5msarett
1260f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettbool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
1261f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                              const void* src, int len, SkAlphaType alphaType) const {
1262f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcColorFormat, src, len,
1263f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                                                     alphaType);
1264f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett}
1265f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
12667bbda991af353fbe6b34132132d211d23a3dba8cmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
12677bbda991af353fbe6b34132132d211d23a3dba8cmsarett
1268f6878baba8c7cd347e185361bac2eabaef863bfaMatt SarettSkColorSpaceXform_Pipeline::SkColorSpaceXform_Pipeline(SkColorSpace_XYZ* srcSpace,
1269f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                                       const SkMatrix44& srcToDst,
1270f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                                       SkColorSpace_XYZ* dstSpace,
1271f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                                       ColorSpaceMatch csm,
1272f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                                       SrcGamma srcGamma,
1273f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                                       DstGamma dstGamma)
1274f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    : fCSM(csm)
1275f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    , fSrcGamma(srcGamma)
1276f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    , fDstGamma(dstGamma)
1277f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett{
1278f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 0] = srcToDst.get(0, 0);
1279f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 1] = srcToDst.get(1, 0);
1280f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 2] = srcToDst.get(2, 0);
1281f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 3] = srcToDst.get(0, 1);
1282f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 4] = srcToDst.get(1, 1);
1283f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 5] = srcToDst.get(2, 1);
1284f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 6] = srcToDst.get(0, 2);
1285f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 7] = srcToDst.get(1, 2);
1286f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 8] = srcToDst.get(2, 2);
1287f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[ 9] = srcToDst.get(0, 3);
1288f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[10] = srcToDst.get(1, 3);
1289f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcToDst[11] = srcToDst.get(2, 3);
1290f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1291f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    const int numSrcTables = num_tables(srcSpace);
1292f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    const size_t srcEntries = numSrcTables * 256;
1293f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    const bool srcGammasAreMatching = (1 >= numSrcTables);
1294f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    fSrcStorage.reset(srcEntries);
1295f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear,
1296f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                       srcGammasAreMatching);
1297f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1298f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    const int numDstTables = num_tables(dstSpace);
1299f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
1300f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett}
1301f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1302f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarettbool SkColorSpaceXform_Pipeline::onApply(ColorFormat dstColorFormat, void* dst,
1303f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                         ColorFormat srcColorFormat, const void* src, int len,
1304f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                                         SkAlphaType alphaType) const {
1305f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kFull_ColorSpaceMatch == fCSM) {
1306f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        if (kPremul_SkAlphaType != alphaType) {
1307f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if ((kRGBA_8888_ColorFormat == dstColorFormat &&
1308f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                 kRGBA_8888_ColorFormat == srcColorFormat) ||
1309f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                (kBGRA_8888_ColorFormat == dstColorFormat &&
1310f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                 kBGRA_8888_ColorFormat == srcColorFormat))
1311f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            {
1312f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                memcpy(dst, src, len * sizeof(uint32_t));
1313f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return true;
1314f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1315f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1316f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if ((kRGBA_8888_ColorFormat == dstColorFormat &&
1317f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                 kBGRA_8888_ColorFormat == srcColorFormat) ||
1318f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                (kBGRA_8888_ColorFormat == dstColorFormat &&
1319f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                 kRGBA_8888_ColorFormat == srcColorFormat))
1320f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            {
1321f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len);
1322f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return true;
1323f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1324f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        }
1325f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1326f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1327f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kRGBA_F16_ColorFormat == srcColorFormat || kRGBA_F32_ColorFormat == srcColorFormat) {
1328f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        return false;
1329f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1330f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1331f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    SkRasterPipeline pipeline;
1332f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1333f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    LoadTablesContext loadTables;
1334f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kLinear_SrcGamma == fSrcGamma) {
1335f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::load_8888, &src);
1336f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        if (kBGRA_8888_ColorFormat == srcColorFormat) {
1337f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::swap_rb);
1338f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        }
1339f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    } else {
1340f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        loadTables.fSrc = (const uint32_t*) src;
1341f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        loadTables.fG = fSrcGammaTables[1];
1342f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        if (kRGBA_8888_ColorFormat == srcColorFormat) {
1343f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            loadTables.fR = fSrcGammaTables[0];
1344f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            loadTables.fB = fSrcGammaTables[2];
1345f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::load_tables, &loadTables);
1346f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        } else {
1347f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            loadTables.fR = fSrcGammaTables[2];
1348f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            loadTables.fB = fSrcGammaTables[0];
1349f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::load_tables, &loadTables);
1350f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::swap_rb);
1351f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        }
1352f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1353f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1354f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kNone_ColorSpaceMatch == fCSM) {
1355f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst);
1356f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1357f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1358f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kRGBA_8888_ColorFormat == dstColorFormat || kBGRA_8888_ColorFormat == dstColorFormat) {
1359f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::clamp_0);
1360f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::clamp_1);
1361f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1362f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1363f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kPremul_SkAlphaType == alphaType) {
1364f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::premul);
1365f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1366f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1367f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    StoreTablesContext storeTables;
1368f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    switch (fDstGamma) {
1369f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kSRGB_DstGamma:
1370f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::to_srgb);
1371f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1372f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case k2Dot2_DstGamma:
1373f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::to_2dot2);
1374f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1375f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        default:
1376f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1377f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1378f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1379f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    switch (dstColorFormat) {
1380f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_8888_ColorFormat:
1381f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if (kTable_DstGamma == fDstGamma) {
1382f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fDst = (uint32_t*) dst;
1383f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fR = fDstGammaTables[0];
1384f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fG = fDstGammaTables[1];
1385f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fB = fDstGammaTables[2];
1386f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize;
1387f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::store_tables, &storeTables);
1388f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            } else {
1389f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::store_8888, &dst);
1390f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1391f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1392f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kBGRA_8888_ColorFormat:
1393f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if (kTable_DstGamma == fDstGamma) {
1394f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fDst = (uint32_t*) dst;
1395f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fR = fDstGammaTables[2];
1396f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fG = fDstGammaTables[1];
1397f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fB = fDstGammaTables[0];
1398f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                storeTables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize;
1399f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::swap_rb);
1400f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::store_tables, &storeTables);
1401f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            } else {
1402f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::swap_rb);
1403f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                pipeline.append(SkRasterPipeline::store_8888, &dst);
1404f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1405f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1406f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F16_ColorFormat:
1407f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
1408f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
1409f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1410f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::store_f16, &dst);
1411f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1412f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F32_ColorFormat:
1413f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
1414f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
1415f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
1416f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::store_f32, &dst);
1417f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
1418f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
1419f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1420f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    pipeline.run(0, 0, len);
1421f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    return true;
1422f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett}
1423f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
1424f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett///////////////////////////////////////////////////////////////////////////////////////////////////
1425f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
14269488833428e83c93a7e6002f4d056084fb57112fraftiasstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
1427f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    if (kUseRasterPipeline) {
1428f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Pipeline(
1429f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                space, SkMatrix::I(), space, kNone_ColorSpaceMatch, kTable_SrcGamma,
1430f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                kTable_DstGamma));
1431f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    } else {
1432f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
14338bbcd5aab81dc0742c3367479c0c9d97363b1203msarett                <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
14349dc6cf6b8833d36c29a23d2519989b069745fcd5msarett                (space, SkMatrix::I(), space));
1435f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
14369dc6cf6b8833d36c29a23d2519989b069745fcd5msarett}
1437