SkColorSpaceXform.cpp revision a4083c97d48e8a4f88e2797d7363f141e3d42553
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
8a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.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"
185e15961fa77281540a80ac0d036fefe071c11574Mike Klein#include "SkPM4fPriv.h"
19f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett#include "SkRasterPipeline.h"
20ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h"
2145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein#include "../jumper/SkJumper.h"
229876ac5b3016e5353c072378ac1545a0a2270757msarett
236006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = {
24b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f,
25b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f,
26b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f,
27b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f,
28b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f,
29b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f,
30b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f,
31b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f,
32b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f,
33b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f,
34b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f,
35b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f,
36b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f,
37b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f,
38b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f,
39b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f,
40b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f,
41b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f,
42b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f,
43b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f,
44b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f,
45b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f,
46b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f,
47b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f,
48b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f,
49b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f,
50b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f,
51b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f,
52b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f,
53b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f,
54b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f,
55b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f,
56b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f,
57b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f,
58b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f,
59b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f,
60b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f,
61b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f,
62b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f,
63b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f,
64b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f,
65b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f,
66b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f,
67b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f,
68b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f,
69b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f,
70b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f,
71b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f,
72b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f,
73b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f,
74b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f,
75b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f,
76b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f,
77b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f,
78b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f,
79b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f,
80b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f,
81b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f,
82b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f,
83b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f,
84b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f,
85b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f,
86b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f,
87b39067696ad08a26bbe49b71a71f0546dc42a075msarett        0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f,
88b39067696ad08a26bbe49b71a71f0546dc42a075msarett};
89b39067696ad08a26bbe49b71a71f0546dc42a075msarett
906006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
916006f678e78af7b6f67a454cd4bc213048983f9dmsarett
9215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) {
9315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
9415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = powf(x, exponent);
9515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
9615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
9715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
9815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett// outTable is always 256 entries, inTable may be larger or smaller.
9915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable,
10015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          int inTableSize) {
10115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    if (256 == inTableSize) {
10215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        memcpy(outTable, inTable, sizeof(float) * 256);
10315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        return;
10415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
10615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
10715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        *outTable++ = interp_lut(x, inTable, inTableSize);
10815ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
10915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
11015ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
111aa34f7ea58330cb73ea17f01715cb6c7d439fae9Matt Sarett
11215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c,
11315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett                                          float d, float e, float f) {
1142410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // Y = (aX + b)^g + e  for X >= d
1152410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // Y = cX + f          otherwise
11615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
11715ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        if (x >= d) {
1182410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett            *outTable++ = clamp_0_1(powf(a * x + b, g) + e);
11915ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        } else {
1202410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett            *outTable++ = clamp_0_1(c * x + f);
12115ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett        }
12215ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett    }
12315ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett}
12415ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
12515ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett///////////////////////////////////////////////////////////////////////////////////////////////////
12615ee3deee8aca2bf6e658449f25ee34a8153e6eemsarett
127f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettstatic const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize;
1283418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett
1291b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) {
130b39067696ad08a26bbe49b71a71f0546dc42a075msarett    float toGammaExp = 1.0f / exponent;
131b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1333418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
134b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp));
135b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
136dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett}
137dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
1381b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable,
139b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        int inTableSize) {
140197e311ac9d15696fae929d8f5fcf9d93ec55e18raftias    invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize);
141b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
142dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
143b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e,
144b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                float f) {
145b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // We need to take the inverse of the following piecewise function.
146b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Y = (aX + b)^g + c  for X >= d
147b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Y = eX + f          otherwise
148b39067696ad08a26bbe49b71a71f0546dc42a075msarett
149b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Assume that the gamma function is continuous, or this won't make much sense anyway.
150b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Plug in |d| to the first equation to calculate the new piecewise interval.
151b39067696ad08a26bbe49b71a71f0546dc42a075msarett    // Then simply use the inverse of the original functions.
1522410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    float interval = c * d + f;
153b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (x < interval) {
1542410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        // X = (Y - F) / C
1552410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        if (0.0f == c) {
156b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // The gamma curve for this segment is constant, so the inverse is undefined.
157b39067696ad08a26bbe49b71a71f0546dc42a075msarett            // Since this is the lower segment, guess zero.
158b39067696ad08a26bbe49b71a71f0546dc42a075msarett            return 0.0f;
159b39067696ad08a26bbe49b71a71f0546dc42a075msarett        }
160b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1612410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett        return (x - f) / c;
162b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
163b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1642410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    // X = ((Y - E)^(1 / G) - B) / A
165b39067696ad08a26bbe49b71a71f0546dc42a075msarett    if (0.0f == a || 0.0f == g) {
166b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // The gamma curve for this segment is constant, so the inverse is undefined.
167b39067696ad08a26bbe49b71a71f0546dc42a075msarett        // Since this is the upper segment, guess one.
168b39067696ad08a26bbe49b71a71f0546dc42a075msarett        return 1.0f;
169b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
170b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1712410717f900c2691db880d84a2e03a6a24905ee2Matt Sarett    return (powf(x - e, 1.0f / g) - b) / a;
172b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
173b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1741b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a,
175b39067696ad08a26bbe49b71a71f0546dc42a075msarett                                        float b, float c, float d, float e, float f) {
1763418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett    for (int i = 0; i < kDstGammaTableSize; i++) {
1773418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1)));
178b39067696ad08a26bbe49b71a71f0546dc42a075msarett        float y = inverse_parametric(x, g, a, b, c, d, e, f);
179b39067696ad08a26bbe49b71a71f0546dc42a075msarett        outTable[i] = clamp_normalized_float_to_byte(y);
180b39067696ad08a26bbe49b71a71f0546dc42a075msarett    }
181b39067696ad08a26bbe49b71a71f0546dc42a075msarett}
182b39067696ad08a26bbe49b71a71f0546dc42a075msarett
1836006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
1846006f678e78af7b6f67a454cd4bc213048983f9dmsarett
1851b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
1861b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns {
1871b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* fSRGBTable;
1881b93bd1e6eba3d14593490e4e24a34546638c8damsarett    const T* f2Dot2Table;
1891b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromValue)(T*, float);
1901b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromTable)(T*, const float*, int);
1911b93bd1e6eba3d14593490e4e24a34546638c8damsarett    void (*fBuildFromParam)(T*, float, float, float, float, float, float, float);
1921b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
1931b93bd1e6eba3d14593490e4e24a34546638c8damsarett
1941b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear {
1951b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_srgb,
1961b93bd1e6eba3d14593490e4e24a34546638c8damsarett    sk_linear_from_2dot2,
1971b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
1981b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
1991b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_from_gamma,
2001b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2011b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2021b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear {
20355bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
20455bcc8e0af3415601b3d62252a0d579fbe87c85amsarett    nullptr,
2051b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2061b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2071b93bd1e6eba3d14593490e4e24a34546638c8damsarett    &build_table_linear_to_gamma,
2081b93bd1e6eba3d14593490e4e24a34546638c8damsarett};
2091b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2101b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear.
2111b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T>
2121b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
2139488833428e83c93a7e6002f4d056084fb57112fraftias                               const SkColorSpace_XYZ* space, const GammaFns<T>& fns,
214f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                               bool gammasAreMatching)
2154be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett{
2169488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
217600c737b64eae2c7379442ae2c852853cce3a278msarett        case kSRGB_SkGammaNamed:
2181b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable;
2191b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
220600c737b64eae2c7379442ae2c852853cce3a278msarett        case k2Dot2Curve_SkGammaNamed:
2211b93bd1e6eba3d14593490e4e24a34546638c8damsarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table;
2221b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
223600c737b64eae2c7379442ae2c852853cce3a278msarett        case kLinear_SkGammaNamed:
2248bbcd5aab81dc0742c3367479c0c9d97363b1203msarett            outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr;
2251b93bd1e6eba3d14593490e4e24a34546638c8damsarett            break;
2261b93bd1e6eba3d14593490e4e24a34546638c8damsarett        default: {
2279488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
2281b93bd1e6eba3d14593490e4e24a34546638c8damsarett            SkASSERT(gammas);
2291b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2307bbda991af353fbe6b34132132d211d23a3dba8cmsarett            auto build_table = [=](int i) {
2311b93bd1e6eba3d14593490e4e24a34546638c8damsarett                if (gammas->isNamed(i)) {
2321b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    switch (gammas->data(i).fNamed) {
233600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kSRGB_SkGammaNamed:
234a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                            (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize],
235a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fG,
236a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fA,
237a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fB,
238a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fC,
239a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fD,
240a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fE,
241a8565e502db3e4c0bcdac04be03751bd8ca99cb1Hal Canary                                                   gSRGB_TransferFn.fF);
24255bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2431b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
244600c737b64eae2c7379442ae2c852853cce3a278msarett                        case k2Dot2Curve_SkGammaNamed:
24555bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f);
24655bcc8e0af3415601b3d62252a0d579fbe87c85amsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2471b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
248600c737b64eae2c7379442ae2c852853cce3a278msarett                        case kLinear_SkGammaNamed:
2491b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f);
2501b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2511b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2521b93bd1e6eba3d14593490e4e24a34546638c8damsarett                        default:
2531b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            SkASSERT(false);
2541b93bd1e6eba3d14593490e4e24a34546638c8damsarett                            break;
2551b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    }
2561b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isValue(i)) {
2571b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize],
2581b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fValue);
2591b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2601b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else if (gammas->isTable(i)) {
2611b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i),
2621b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           gammas->data(i).fTable.fSize);
2631b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2641b93bd1e6eba3d14593490e4e24a34546638c8damsarett                } else {
2651b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    SkASSERT(gammas->isParametric(i));
266df44fc5f2bb282557df291e20dbd26c070533aa6Matt Sarett                    const SkColorSpaceTransferFn& params = gammas->params(i);
2671b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG,
2681b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fA, params.fB, params.fC, params.fD, params.fE,
2691b93bd1e6eba3d14593490e4e24a34546638c8damsarett                                           params.fF);
2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett                    outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
2711b93bd1e6eba3d14593490e4e24a34546638c8damsarett                }
2727bbda991af353fbe6b34132132d211d23a3dba8cmsarett            };
2737bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2747bbda991af353fbe6b34132132d211d23a3dba8cmsarett            if (gammasAreMatching) {
2757bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2767bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[1] = outGammaTables[0];
2777bbda991af353fbe6b34132132d211d23a3dba8cmsarett                outGammaTables[2] = outGammaTables[0];
2787bbda991af353fbe6b34132132d211d23a3dba8cmsarett            } else {
2797bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(0);
2807bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(1);
2817bbda991af353fbe6b34132132d211d23a3dba8cmsarett                build_table(2);
2821b93bd1e6eba3d14593490e4e24a34546638c8damsarett            }
2837bbda991af353fbe6b34132132d211d23a3dba8cmsarett
2847bbda991af353fbe6b34132132d211d23a3dba8cmsarett            break;
2851b93bd1e6eba3d14593490e4e24a34546638c8damsarett        }
2861b93bd1e6eba3d14593490e4e24a34546638c8damsarett    }
2871b93bd1e6eba3d14593490e4e24a34546638c8damsarett}
2881b93bd1e6eba3d14593490e4e24a34546638c8damsarett
289f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettvoid SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3],
2909488833428e83c93a7e6002f4d056084fb57112fraftias                                                 uint8_t* dstStorage,
2919488833428e83c93a7e6002f4d056084fb57112fraftias                                                 const SkColorSpace_XYZ* space,
292f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                                                 bool gammasAreMatching) {
293f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear,
294f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       gammasAreMatching);
295f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett}
296f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
2971b93bd1e6eba3d14593490e4e24a34546638c8damsarett///////////////////////////////////////////////////////////////////////////////////////////////////
2981b93bd1e6eba3d14593490e4e24a34546638c8damsarett
2994be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace,
3004be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett                                                          SkColorSpace* dstSpace) {
301cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    return SkColorSpaceXform_Base::New(srcSpace, dstSpace, SkTransferFunctionBehavior::kRespect);
302cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett}
303cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett
304cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform_Base::New(SkColorSpace* srcSpace,
305cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett        SkColorSpace* dstSpace, SkTransferFunctionBehavior premulBehavior) {
306cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett
3076006f678e78af7b6f67a454cd4bc213048983f9dmsarett    if (!srcSpace || !dstSpace) {
3086006f678e78af7b6f67a454cd4bc213048983f9dmsarett        // Invalid input
3096006f678e78af7b6f67a454cd4bc213048983f9dmsarett        return nullptr;
3106006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3116006f678e78af7b6f67a454cd4bc213048983f9dmsarett
3129488833428e83c93a7e6002f4d056084fb57112fraftias    if (SkColorSpace_Base::Type::kA2B == as_CSB(dstSpace)->type()) {
3132563601fc2b0505619f905f86bd249ae630197ccraftias        SkCSXformPrintf("A2B destinations not supported\n");
3149488833428e83c93a7e6002f4d056084fb57112fraftias        return nullptr;
3159488833428e83c93a7e6002f4d056084fb57112fraftias    }
3169488833428e83c93a7e6002f4d056084fb57112fraftias
3179488833428e83c93a7e6002f4d056084fb57112fraftias    if (SkColorSpace_Base::Type::kA2B == as_CSB(srcSpace)->type()) {
3182563601fc2b0505619f905f86bd249ae630197ccraftias        SkColorSpace_A2B* src = static_cast<SkColorSpace_A2B*>(srcSpace);
3192563601fc2b0505619f905f86bd249ae630197ccraftias        SkColorSpace_XYZ* dst = static_cast<SkColorSpace_XYZ*>(dstSpace);
3202563601fc2b0505619f905f86bd249ae630197ccraftias        return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B(src, dst));
3219488833428e83c93a7e6002f4d056084fb57112fraftias    }
3229488833428e83c93a7e6002f4d056084fb57112fraftias    SkColorSpace_XYZ* srcSpaceXYZ = static_cast<SkColorSpace_XYZ*>(srcSpace);
3239488833428e83c93a7e6002f4d056084fb57112fraftias    SkColorSpace_XYZ* dstSpaceXYZ = static_cast<SkColorSpace_XYZ*>(dstSpace);
3249488833428e83c93a7e6002f4d056084fb57112fraftias
325200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    ColorSpaceMatch csm = kNone_ColorSpaceMatch;
3266006f678e78af7b6f67a454cd4bc213048983f9dmsarett    SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
327f3880933092c3226cd7ffd1690fe72c9c0cc376cMatt Sarett    if (SkColorSpace::Equals(srcSpace, dstSpace)) {
328200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        srcToDst.setIdentity();
329200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        csm = kFull_ColorSpaceMatch;
330971cd496b9e25f87f3a75a0015c203322907136abrianosman    } else {
331bbf251bf225489a0939fff6df938035a290f4d16Brian Osman        if (srcSpaceXYZ->toXYZD50Hash() == dstSpaceXYZ->toXYZD50Hash()) {
332bbf251bf225489a0939fff6df938035a290f4d16Brian Osman            SkASSERT(*srcSpaceXYZ->toXYZD50() == *dstSpaceXYZ->toXYZD50() && "Hash collision");
333971cd496b9e25f87f3a75a0015c203322907136abrianosman            srcToDst.setIdentity();
334971cd496b9e25f87f3a75a0015c203322907136abrianosman            csm = kGamut_ColorSpaceMatch;
335bbf251bf225489a0939fff6df938035a290f4d16Brian Osman        } else {
336bbf251bf225489a0939fff6df938035a290f4d16Brian Osman            srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50());
337971cd496b9e25f87f3a75a0015c203322907136abrianosman        }
3386006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3396006f678e78af7b6f67a454cd4bc213048983f9dmsarett
340200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett    switch (csm) {
341200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kNone_ColorSpaceMatch:
342379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
343cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett                    <kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
344200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kGamut_ColorSpaceMatch:
345379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
346cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett                    <kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
347200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett        case kFull_ColorSpaceMatch:
348379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
349cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett                    <kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ, premulBehavior));
3503418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett        default:
351200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            SkASSERT(false);
352200877eecaba782e56a1dd9e13a92f36d7b1ba12msarett            return nullptr;
3536006f678e78af7b6f67a454cd4bc213048983f9dmsarett    }
3546006f678e78af7b6f67a454cd4bc213048983f9dmsarett}
3556006f678e78af7b6f67a454cd4bc213048983f9dmsarett
3566006f678e78af7b6f67a454cd4bc213048983f9dmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
3576006f678e78af7b6f67a454cd4bc213048983f9dmsarett
358e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Kleinstatic inline int num_tables(SkColorSpace_XYZ* space) {
3599488833428e83c93a7e6002f4d056084fb57112fraftias    switch (space->gammaNamed()) {
3607bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kSRGB_SkGammaNamed:
3617bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case k2Dot2Curve_SkGammaNamed:
3627bbda991af353fbe6b34132132d211d23a3dba8cmsarett        case kLinear_SkGammaNamed:
3637bbda991af353fbe6b34132132d211d23a3dba8cmsarett            return 0;
3647bbda991af353fbe6b34132132d211d23a3dba8cmsarett        default: {
3659488833428e83c93a7e6002f4d056084fb57112fraftias            const SkGammas* gammas = space->gammas();
3667bbda991af353fbe6b34132132d211d23a3dba8cmsarett            SkASSERT(gammas);
3677bbda991af353fbe6b34132132d211d23a3dba8cmsarett
3687bbda991af353fbe6b34132132d211d23a3dba8cmsarett            bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) &&
3697bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->data(0) == gammas->data(1)) &&
3707bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->type(0) == gammas->type(2)) &&
3717bbda991af353fbe6b34132132d211d23a3dba8cmsarett                                     (gammas->data(0) == gammas->data(2));
3727bbda991af353fbe6b34132132d211d23a3dba8cmsarett
3737bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // It's likely that each component will have the same gamma.  In this case,
3747bbda991af353fbe6b34132132d211d23a3dba8cmsarett            // we only need to build one table.
3757bbda991af353fbe6b34132132d211d23a3dba8cmsarett            return gammasAreMatching ? 1 : 3;
3767bbda991af353fbe6b34132132d211d23a3dba8cmsarett        }
3777bbda991af353fbe6b34132132d211d23a3dba8cmsarett    }
3787bbda991af353fbe6b34132132d211d23a3dba8cmsarett}
3797bbda991af353fbe6b34132132d211d23a3dba8cmsarett
380379938e47bc9edb6edfd21aabefa01aed71dd135Matt Saretttemplate <ColorSpaceMatch kCSM>
381379938e47bc9edb6edfd21aabefa01aed71dd135Matt SarettSkColorSpaceXform_XYZ<kCSM>
3829488833428e83c93a7e6002f4d056084fb57112fraftias::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
383cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett                        SkColorSpace_XYZ* dstSpace, SkTransferFunctionBehavior premulBehavior)
384cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    : fPremulBehavior(premulBehavior)
3853418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett{
38626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 0] = srcToDst.get(0, 0);
38726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 1] = srcToDst.get(1, 0);
38826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 2] = srcToDst.get(2, 0);
38926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 3] = srcToDst.get(0, 1);
39026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 4] = srcToDst.get(1, 1);
39126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 5] = srcToDst.get(2, 1);
39226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 6] = srcToDst.get(0, 2);
39326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 7] = srcToDst.get(1, 2);
39426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 8] = srcToDst.get(2, 2);
39526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[ 9] = srcToDst.get(0, 3);
39626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[10] = srcToDst.get(1, 3);
39726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[11] = srcToDst.get(2, 3);
39826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    fSrcToDst[12] = 0.0f;
3997bbda991af353fbe6b34132132d211d23a3dba8cmsarett
4004be0e7cfe0efceeaf4c7a4d598d77c27cfd3e69bmsarett    const int numSrcTables = num_tables(srcSpace);
401f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    const size_t srcEntries = numSrcTables * 256;
4027bbda991af353fbe6b34132132d211d23a3dba8cmsarett    const bool srcGammasAreMatching = (1 >= numSrcTables);
403f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    fSrcStorage.reset(srcEntries);
404f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear,
405f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                       srcGammasAreMatching);
406f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
407f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    const int numDstTables = num_tables(dstSpace);
4089488833428e83c93a7e6002f4d056084fb57112fraftias    dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
409379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett
410379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    if (srcSpace->gammaIsLinear()) {
411379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kLinear_SrcGamma;
412379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    } else if (kSRGB_SkGammaNamed == srcSpace->gammaNamed()) {
413379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kSRGB_SrcGamma;
414379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    } else {
415379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        fSrcGamma = kTable_SrcGamma;
416379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    }
417379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett
418379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    switch (dstSpace->gammaNamed()) {
419379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kSRGB_SkGammaNamed:
420379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kSRGB_DstGamma;
421379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
422379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case k2Dot2Curve_SkGammaNamed:
423379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = k2Dot2_DstGamma;
424379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
425379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kLinear_SkGammaNamed:
426379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kLinear_DstGamma;
427379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
428379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        default:
429379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            fDstGamma = kTable_DstGamma;
430379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
431379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    }
4323418c0e797e2ee841d1c031ca9d7a5ba73205f51msarett}
433dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett
4347bbda991af353fbe6b34132132d211d23a3dba8cmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
4357bbda991af353fbe6b34132132d211d23a3dba8cmsarett
4361f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Kleintemplate <ColorSpaceMatch kCSM>
437e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Kleinbool SkColorSpaceXform_XYZ<kCSM>::onApply(ColorFormat dstColorFormat, void* dst,
438e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein                                          ColorFormat srcColorFormat, const void* src,
439e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein                                          int len, SkAlphaType alphaType) const {
440e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein    if (kFull_ColorSpaceMatch == kCSM && kPremul_SkAlphaType != alphaType) {
441e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        if ((kRGBA_8888_ColorFormat == dstColorFormat &&
442e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kRGBA_8888_ColorFormat == srcColorFormat) ||
443e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            (kBGRA_8888_ColorFormat == dstColorFormat &&
444e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kBGRA_8888_ColorFormat == srcColorFormat))
445e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        {
446e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            memcpy(dst, src, len * sizeof(uint32_t));
447e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            return true;
44858564425e5acb5911cc3719f9c1e39190cc829b8Mike Klein        }
44926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett
450e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        if ((kRGBA_8888_ColorFormat == dstColorFormat &&
451e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kBGRA_8888_ColorFormat == srcColorFormat) ||
452e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            (kBGRA_8888_ColorFormat == dstColorFormat &&
453e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein             kRGBA_8888_ColorFormat == srcColorFormat))
454e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        {
455e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            SkOpts::RGBA_to_BGRA((uint32_t*)dst, src, len);
456e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein            return true;
457e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein        }
4581f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein    }
4591f8796dbde0dd2cd146e051e88def2c1c23f5d9cMike Klein
460e23e55ef33358b2f6f98fc9cb795c71397c01618Mike Klein    return this->applyPipeline(dstColorFormat, dst, srcColorFormat, src, len, alphaType);
4619ce3a543c92a73e6daca420defc042886b3f2019msarett}
4629dc6cf6b8833d36c29a23d2519989b069745fcd5msarett
463f489886915034093278353d06c6f1973b2e8b7d2Matt Sarettbool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
464f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                              const void* src, int len, SkAlphaType alphaType) const {
465f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett    return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcColorFormat, src, len,
466f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett                                                     alphaType);
467f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett}
468f489886915034093278353d06c6f1973b2e8b7d2Matt Sarett
469edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reedbool SkColorSpaceXform::Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst,
470edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed                              SkColorSpace* srcCS, ColorFormat srcFormat, const void* src,
471edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed                              int count, AlphaOp op) {
472edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed    SkAlphaType at;
473edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed    switch (op) {
474edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed        case kPreserve_AlphaOp:    at = kUnpremul_SkAlphaType; break;
475edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed        case kPremul_AlphaOp:      at = kPremul_SkAlphaType;   break;
476edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed        case kSrcIsOpaque_AlphaOp: at = kOpaque_SkAlphaType;   break;
477edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed    }
478edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed    return New(srcCS, dstCS)->apply(dstFormat, dst, srcFormat, src, count, at);
479edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed}
480edf8a762190eccc6d2a7ab3a095d131e9fd101bcMike Reed
4817bbda991af353fbe6b34132132d211d23a3dba8cmsarett///////////////////////////////////////////////////////////////////////////////////////////////////
4827bbda991af353fbe6b34132132d211d23a3dba8cmsarett
483379938e47bc9edb6edfd21aabefa01aed71dd135Matt Saretttemplate <ColorSpaceMatch kCSM>
484379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarettbool SkColorSpaceXform_XYZ<kCSM>
48526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett::applyPipeline(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
48626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                const void* src, int len, SkAlphaType alphaType) const {
487b24704d35f67f5b460be9c92794892e06adceb46Mike Klein    SkRasterPipeline_<256> pipeline;
488f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
48945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein    SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
49045c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                       dst_ctx = { (void*)dst, 0 };
49145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein
49226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    LoadTablesContext loadTables;
49326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    switch (srcColorFormat) {
49426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett        case kRGBA_8888_ColorFormat:
495379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            if (kLinear_SrcGamma == fSrcGamma) {
49645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                pipeline.append(SkRasterPipeline::load_8888, &src_ctx);
49726a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            } else {
498379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                loadTables.fSrc = src;
49926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fR = fSrcGammaTables[0];
50026a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fG = fSrcGammaTables[1];
50126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fB = fSrcGammaTables[2];
50226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                pipeline.append(SkRasterPipeline::load_tables, &loadTables);
503f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
504f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
50526a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            break;
50626a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett        case kBGRA_8888_ColorFormat:
507379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            if (kLinear_SrcGamma == fSrcGamma) {
50845c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                pipeline.append(SkRasterPipeline::load_bgra, &src_ctx);
50926a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            } else {
510379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                loadTables.fSrc = src;
51126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fR = fSrcGammaTables[2];
51226a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fG = fSrcGammaTables[1];
51326a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                loadTables.fB = fSrcGammaTables[0];
51426a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett                pipeline.append(SkRasterPipeline::load_tables, &loadTables);
515c2d207603edbbd3809d5144fe4a048a2ad774910Mike Klein                pipeline.append(SkRasterPipeline::swap_rb);
516f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
517f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
51826a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett            break;
519b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman        case kRGBA_F16_ColorFormat:
520b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            if (kLinear_SrcGamma != fSrcGamma) {
521b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman                return false;
522b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            }
52345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::load_f16, &src_ctx);
524b1168a7c9a360bf80b447e2e399bdc5721d5152eBrian Osman            break;
5254c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett        case kRGBA_F32_ColorFormat:
5264c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            if (kLinear_SrcGamma != fSrcGamma) {
5274c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett                return false;
5284c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            }
52945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::load_f32, &src_ctx);
5304c55027dbf57d0701361b123e36b8fad46c341c3Matt Sarett            break;
531379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        case kRGBA_U16_BE_ColorFormat:
532379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            switch (fSrcGamma) {
533379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kLinear_SrcGamma:
53445c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx);
535379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
536379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kSRGB_SrcGamma:
53745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_u16_be, &src_ctx);
538379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    pipeline.append_from_srgb(kUnpremul_SkAlphaType);
539379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
540379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                case kTable_SrcGamma:
541379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fSrc = src;
542379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fR = fSrcGammaTables[0];
543379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fG = fSrcGammaTables[1];
544379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    loadTables.fB = fSrcGammaTables[2];
545379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables);
546379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett                    break;
547379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            }
548379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            break;
5495bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett        case kRGB_U16_BE_ColorFormat:
5505bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            switch (fSrcGamma) {
5515bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kLinear_SrcGamma:
55245c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx);
5535bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
5545bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kSRGB_SrcGamma:
55545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein                    pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src_ctx);
5565bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    pipeline.append_from_srgb(kUnpremul_SkAlphaType);
5575bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
5585bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                case kTable_SrcGamma:
5595bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fSrc = src;
5605bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fR = fSrcGammaTables[0];
5615bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fG = fSrcGammaTables[1];
5625bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    loadTables.fB = fSrcGammaTables[2];
5635bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    pipeline.append(SkRasterPipeline::load_tables_rgb_u16_be, &loadTables);
5645bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett                    break;
5655bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            }
5665bee0b6de6b3ad1166d067e6b5046b48b8240a29Matt Sarett            break;
5673725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett        default:
5683725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            return false;
569f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
570f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
57126a0543579cf7473de2099ce0d056ac8aba83811Matt Sarett    if (kNone_ColorSpaceMatch == kCSM) {
572f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst);
573f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
574eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett        if (kRGBA_F16_ColorFormat != dstColorFormat &&
575eeb3cb1286c5ca8104da62fb36b07bb0fe04aee5Matt Sarett            kRGBA_F32_ColorFormat != dstColorFormat)
5768f7a9a9bfb51a00082bde7eb6b04515b935a588fMatt Sarett        {
5775e15961fa77281540a80ac0d036fefe071c11574Mike Klein            bool need_clamp_0, need_clamp_1;
5785e15961fa77281540a80ac0d036fefe071c11574Mike Klein            analyze_3x4_matrix(fSrcToDst, &need_clamp_0, &need_clamp_1);
5795e15961fa77281540a80ac0d036fefe071c11574Mike Klein
5805e15961fa77281540a80ac0d036fefe071c11574Mike Klein            if (need_clamp_0) { pipeline.append(SkRasterPipeline::clamp_0); }
5815e15961fa77281540a80ac0d036fefe071c11574Mike Klein            if (need_clamp_1) { pipeline.append(SkRasterPipeline::clamp_1); }
5825e15961fa77281540a80ac0d036fefe071c11574Mike Klein        }
583f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
584f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
585cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kRespect == fPremulBehavior)
586cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    {
587f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        pipeline.append(SkRasterPipeline::premul);
588f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
589f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
590e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett    TablesContext tables;
591a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein    float to_2dot2 = 1/2.2f;
592379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett    switch (fDstGamma) {
593f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kSRGB_DstGamma:
594f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            pipeline.append(SkRasterPipeline::to_srgb);
595f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
596f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case k2Dot2_DstGamma:
597a07e4302cfefc282d8d235edfbc20a54c75afa88Mike Klein            pipeline.append(SkRasterPipeline::gamma, &to_2dot2);
598f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
599e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett        case kTable_DstGamma:
600e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fR = fDstGammaTables[0];
601e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fG = fDstGammaTables[1];
602e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fB = fDstGammaTables[2];
603e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            tables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize;
604e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett            pipeline.append(SkRasterPipeline::byte_tables_rgb, &tables);
605f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        default:
606f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
607f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
608f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
609cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    if (kPremul_SkAlphaType == alphaType && SkTransferFunctionBehavior::kIgnore == fPremulBehavior)
610cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    {
611e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett        pipeline.append(SkRasterPipeline::premul);
612e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett    }
613e522f4c455d0d5dbe813f38d16c0d4cd46fa5deeMatt Sarett
614f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    switch (dstColorFormat) {
615f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_8888_ColorFormat:
61645c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein             pipeline.append(SkRasterPipeline::store_8888, &dst_ctx);
617f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
618f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kBGRA_8888_ColorFormat:
61945c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_bgra, &dst_ctx);
620f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
621f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F16_ColorFormat:
622cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
623f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
624f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
62545c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_f16, &dst_ctx);
626f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
627f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett        case kRGBA_F32_ColorFormat:
628cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett            if (kLinear_DstGamma != fDstGamma) {
629f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett                return false;
630f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            }
63145c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_f32, &dst_ctx);
632f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett            break;
6333725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett        case kBGR_565_ColorFormat:
6343725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            if (kOpaque_SkAlphaType != alphaType) {
6353725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett                return false;
6363725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            }
63745c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein            pipeline.append(SkRasterPipeline::store_565, &dst_ctx);
6383725f0a7dd2916c10bc6d0059821e19a5b4452c3Matt Sarett            break;
639379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett        default:
640379938e47bc9edb6edfd21aabefa01aed71dd135Matt Sarett            return false;
641f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    }
642f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
64345c16fa82cd2fec010d4cb7763b654a413cabd0cMike Klein    pipeline.run(0,0, len,1);
644f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett    return true;
645f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett}
646f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
647f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett///////////////////////////////////////////////////////////////////////////////////////////////////
648f6878baba8c7cd347e185361bac2eabaef863bfaMatt Sarett
6499488833428e83c93a7e6002f4d056084fb57112fraftiasstd::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
650cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett    return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ<kNone_ColorSpaceMatch>
651cf3f2347c8933596aeba873d4ece597a9339392fMatt Sarett            (space, SkMatrix::I(), space, SkTransferFunctionBehavior::kRespect));
6529dc6cf6b8833d36c29a23d2519989b069745fcd5msarett}
653