msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "SkColorPriv.h" |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 9 | #include "SkColorSpace_A2B.h" |
msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 10 | #include "SkColorSpace_Base.h" |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 11 | #include "SkColorSpace_XYZ.h" |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 12 | #include "SkColorSpacePriv.h" |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 13 | #include "SkColorSpaceXform_A2B.h" |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 14 | #include "SkColorSpaceXform_Base.h" |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 15 | #include "SkColorSpaceXformPriv.h" |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 16 | #include "SkHalf.h" |
| 17 | #include "SkOpts.h" |
Mike Klein | 5e15961 | 2016-12-01 16:39:21 -0500 | [diff] [blame] | 18 | #include "SkPM4fPriv.h" |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 19 | #include "SkRasterPipeline.h" |
mtklein | ac41bac | 2016-07-08 06:33:16 -0700 | [diff] [blame] | 20 | #include "SkSRGB.h" |
msarett | 9876ac5 | 2016-06-01 14:47:18 -0700 | [diff] [blame] | 21 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 22 | static constexpr float sk_linear_from_2dot2[256] = { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 23 | 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, |
| 24 | 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, |
| 25 | 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, |
| 26 | 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, |
| 27 | 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, |
| 28 | 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, |
| 29 | 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, |
| 30 | 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, |
| 31 | 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, |
| 32 | 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, |
| 33 | 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, |
| 34 | 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, |
| 35 | 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, |
| 36 | 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, |
| 37 | 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, |
| 38 | 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, |
| 39 | 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, |
| 40 | 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, |
| 41 | 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, |
| 42 | 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, |
| 43 | 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, |
| 44 | 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, |
| 45 | 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, |
| 46 | 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, |
| 47 | 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, |
| 48 | 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, |
| 49 | 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, |
| 50 | 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, |
| 51 | 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, |
| 52 | 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, |
| 53 | 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, |
| 54 | 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, |
| 55 | 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, |
| 56 | 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, |
| 57 | 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, |
| 58 | 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, |
| 59 | 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, |
| 60 | 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, |
| 61 | 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, |
| 62 | 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, |
| 63 | 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, |
| 64 | 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, |
| 65 | 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, |
| 66 | 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, |
| 67 | 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, |
| 68 | 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, |
| 69 | 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, |
| 70 | 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, |
| 71 | 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, |
| 72 | 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, |
| 73 | 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, |
| 74 | 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, |
| 75 | 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, |
| 76 | 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, |
| 77 | 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, |
| 78 | 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, |
| 79 | 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, |
| 80 | 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, |
| 81 | 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, |
| 82 | 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, |
| 83 | 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, |
| 84 | 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, |
| 85 | 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, |
| 86 | 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, |
| 87 | }; |
| 88 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 89 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 90 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 91 | static void build_table_linear_from_gamma(float* outTable, float exponent) { |
| 92 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 93 | *outTable++ = powf(x, exponent); |
| 94 | } |
| 95 | } |
| 96 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 97 | // outTable is always 256 entries, inTable may be larger or smaller. |
| 98 | static void build_table_linear_from_gamma(float* outTable, const float* inTable, |
| 99 | int inTableSize) { |
| 100 | if (256 == inTableSize) { |
| 101 | memcpy(outTable, inTable, sizeof(float) * 256); |
| 102 | return; |
| 103 | } |
| 104 | |
| 105 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 106 | *outTable++ = interp_lut(x, inTable, inTableSize); |
| 107 | } |
| 108 | } |
| 109 | |
Matt Sarett | aa34f7e | 2016-11-09 18:14:47 -0500 | [diff] [blame] | 110 | |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 111 | static void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, |
| 112 | float d, float e, float f) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 113 | // Y = (aX + b)^g + e for X >= d |
| 114 | // Y = cX + f otherwise |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 115 | for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
| 116 | if (x >= d) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 117 | *outTable++ = clamp_0_1(powf(a * x + b, g) + e); |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 118 | } else { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 119 | *outTable++ = clamp_0_1(c * x + f); |
msarett | 15ee3de | 2016-08-02 11:30:30 -0700 | [diff] [blame] | 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 125 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 126 | static const int kDstGammaTableSize = SkColorSpaceXform_Base::kDstGammaTableSize; |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 127 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 128 | static void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 129 | float toGammaExp = 1.0f / exponent; |
| 130 | |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 131 | for (int i = 0; i < kDstGammaTableSize; i++) { |
| 132 | float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 133 | outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); |
| 134 | } |
msarett | dc27a64 | 2016-06-06 12:02:31 -0700 | [diff] [blame] | 135 | } |
| 136 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 137 | static void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 138 | int inTableSize) { |
raftias | 197e311 | 2016-12-01 15:31:29 -0500 | [diff] [blame] | 139 | invert_table_gamma(nullptr, outTable, kDstGammaTableSize, inTable, inTableSize); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | static float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, |
| 143 | float f) { |
| 144 | // We need to take the inverse of the following piecewise function. |
| 145 | // Y = (aX + b)^g + c for X >= d |
| 146 | // Y = eX + f otherwise |
| 147 | |
| 148 | // Assume that the gamma function is continuous, or this won't make much sense anyway. |
| 149 | // Plug in |d| to the first equation to calculate the new piecewise interval. |
| 150 | // Then simply use the inverse of the original functions. |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 151 | float interval = c * d + f; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 152 | if (x < interval) { |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 153 | // X = (Y - F) / C |
| 154 | if (0.0f == c) { |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 155 | // The gamma curve for this segment is constant, so the inverse is undefined. |
| 156 | // Since this is the lower segment, guess zero. |
| 157 | return 0.0f; |
| 158 | } |
| 159 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 160 | return (x - f) / c; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 161 | } |
| 162 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 163 | // X = ((Y - E)^(1 / G) - B) / A |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 164 | if (0.0f == a || 0.0f == g) { |
| 165 | // The gamma curve for this segment is constant, so the inverse is undefined. |
| 166 | // Since this is the upper segment, guess one. |
| 167 | return 1.0f; |
| 168 | } |
| 169 | |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 170 | return (powf(x - e, 1.0f / g) - b) / a; |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 171 | } |
| 172 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 173 | static void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 174 | float b, float c, float d, float e, float f) { |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 175 | for (int i = 0; i < kDstGammaTableSize; i++) { |
| 176 | float x = ((float) i) * (1.0f / ((float) (kDstGammaTableSize - 1))); |
msarett | b390676 | 2016-06-22 14:07:48 -0700 | [diff] [blame] | 177 | float y = inverse_parametric(x, g, a, b, c, d, e, f); |
| 178 | outTable[i] = clamp_normalized_float_to_byte(y); |
| 179 | } |
| 180 | } |
| 181 | |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 182 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 183 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 184 | template <typename T> |
| 185 | struct GammaFns { |
| 186 | const T* fSRGBTable; |
| 187 | const T* f2Dot2Table; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 188 | void (*fBuildFromValue)(T*, float); |
| 189 | void (*fBuildFromTable)(T*, const float*, int); |
| 190 | void (*fBuildFromParam)(T*, float, float, float, float, float, float, float); |
| 191 | }; |
| 192 | |
| 193 | static const GammaFns<float> kToLinear { |
| 194 | sk_linear_from_srgb, |
| 195 | sk_linear_from_2dot2, |
| 196 | &build_table_linear_from_gamma, |
| 197 | &build_table_linear_from_gamma, |
| 198 | &build_table_linear_from_gamma, |
| 199 | }; |
| 200 | |
| 201 | static const GammaFns<uint8_t> kFromLinear { |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 202 | nullptr, |
| 203 | nullptr, |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 204 | &build_table_linear_to_gamma, |
| 205 | &build_table_linear_to_gamma, |
| 206 | &build_table_linear_to_gamma, |
| 207 | }; |
| 208 | |
| 209 | // Build tables to transform src gamma to linear. |
| 210 | template <typename T> |
| 211 | static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 212 | const SkColorSpace_XYZ* space, const GammaFns<T>& fns, |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 213 | bool gammasAreMatching) |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 214 | { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 215 | switch (space->gammaNamed()) { |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 216 | case kSRGB_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 217 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; |
| 218 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 219 | case k2Dot2Curve_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 220 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table; |
| 221 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 222 | case kLinear_SkGammaNamed: |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 223 | outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 224 | break; |
| 225 | default: { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 226 | const SkGammas* gammas = space->gammas(); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 227 | SkASSERT(gammas); |
| 228 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 229 | auto build_table = [=](int i) { |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 230 | if (gammas->isNamed(i)) { |
| 231 | switch (gammas->data(i).fNamed) { |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 232 | case kSRGB_SkGammaNamed: |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 233 | (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], 2.4f, |
Matt Sarett | 2410717 | 2016-12-19 14:33:35 -0500 | [diff] [blame] | 234 | (1.0f / 1.055f), (0.055f / 1.055f), |
| 235 | (1.0f / 12.92f), 0.04045f, 0.0f, 0.0f); |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 236 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 237 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 238 | case k2Dot2Curve_SkGammaNamed: |
msarett | 55bcc8e | 2016-09-09 07:48:05 -0700 | [diff] [blame] | 239 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 2.2f); |
| 240 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 241 | break; |
msarett | 600c737 | 2016-09-07 12:03:53 -0700 | [diff] [blame] | 242 | case kLinear_SkGammaNamed: |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 243 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f); |
| 244 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 245 | break; |
| 246 | default: |
| 247 | SkASSERT(false); |
| 248 | break; |
| 249 | } |
| 250 | } else if (gammas->isValue(i)) { |
| 251 | (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], |
| 252 | gammas->data(i).fValue); |
| 253 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 254 | } else if (gammas->isTable(i)) { |
| 255 | (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i), |
| 256 | gammas->data(i).fTable.fSize); |
| 257 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 258 | } else { |
| 259 | SkASSERT(gammas->isParametric(i)); |
Matt Sarett | df44fc5 | 2016-10-11 16:57:50 -0400 | [diff] [blame] | 260 | const SkColorSpaceTransferFn& params = gammas->params(i); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 261 | (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG, |
| 262 | params.fA, params.fB, params.fC, params.fD, params.fE, |
| 263 | params.fF); |
| 264 | outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; |
| 265 | } |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 266 | }; |
| 267 | |
| 268 | if (gammasAreMatching) { |
| 269 | build_table(0); |
| 270 | outGammaTables[1] = outGammaTables[0]; |
| 271 | outGammaTables[2] = outGammaTables[0]; |
| 272 | } else { |
| 273 | build_table(0); |
| 274 | build_table(1); |
| 275 | build_table(2); |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 276 | } |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 277 | |
| 278 | break; |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 279 | } |
| 280 | } |
| 281 | } |
| 282 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 283 | void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3], |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 284 | uint8_t* dstStorage, |
| 285 | const SkColorSpace_XYZ* space, |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 286 | bool gammasAreMatching) { |
| 287 | build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kFromLinear, |
| 288 | gammasAreMatching); |
| 289 | } |
| 290 | |
msarett | 1b93bd1 | 2016-07-21 07:11:26 -0700 | [diff] [blame] | 291 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 292 | |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 293 | std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace, |
| 294 | SkColorSpace* dstSpace) { |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 295 | if (!srcSpace || !dstSpace) { |
| 296 | // Invalid input |
| 297 | return nullptr; |
| 298 | } |
| 299 | |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 300 | if (SkColorSpace_Base::Type::kA2B == as_CSB(dstSpace)->type()) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 301 | SkCSXformPrintf("A2B destinations not supported\n"); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 302 | return nullptr; |
| 303 | } |
| 304 | |
| 305 | if (SkColorSpace_Base::Type::kA2B == as_CSB(srcSpace)->type()) { |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 306 | SkColorSpace_A2B* src = static_cast<SkColorSpace_A2B*>(srcSpace); |
| 307 | SkColorSpace_XYZ* dst = static_cast<SkColorSpace_XYZ*>(dstSpace); |
| 308 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B(src, dst)); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 309 | } |
| 310 | SkColorSpace_XYZ* srcSpaceXYZ = static_cast<SkColorSpace_XYZ*>(srcSpace); |
| 311 | SkColorSpace_XYZ* dstSpaceXYZ = static_cast<SkColorSpace_XYZ*>(dstSpace); |
| 312 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 313 | ColorSpaceMatch csm = kNone_ColorSpaceMatch; |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 314 | SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 315 | if (SkColorSpace::Equals(srcSpace, dstSpace)) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 316 | srcToDst.setIdentity(); |
| 317 | csm = kFull_ColorSpaceMatch; |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 318 | } else { |
Brian Osman | bbf251b | 2016-10-19 14:56:07 -0400 | [diff] [blame] | 319 | if (srcSpaceXYZ->toXYZD50Hash() == dstSpaceXYZ->toXYZD50Hash()) { |
| 320 | SkASSERT(*srcSpaceXYZ->toXYZD50() == *dstSpaceXYZ->toXYZD50() && "Hash collision"); |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 321 | srcToDst.setIdentity(); |
| 322 | csm = kGamut_ColorSpaceMatch; |
Brian Osman | bbf251b | 2016-10-19 14:56:07 -0400 | [diff] [blame] | 323 | } else { |
| 324 | srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50()); |
brianosman | 971cd49 | 2016-09-08 10:10:11 -0700 | [diff] [blame] | 325 | } |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 326 | } |
| 327 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 328 | switch (csm) { |
| 329 | case kNone_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 330 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
| 331 | <kNone_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 332 | case kGamut_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 333 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
| 334 | <kGamut_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 335 | case kFull_ColorSpaceMatch: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 336 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
| 337 | <kFull_ColorSpaceMatch>(srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 338 | default: |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 339 | SkASSERT(false); |
| 340 | return nullptr; |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 341 | } |
msarett | 6006f67 | 2016-07-11 05:49:17 -0700 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 345 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 346 | #define AI SK_ALWAYS_INLINE |
| 347 | |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 348 | static AI void load_matrix(const float matrix[13], |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 349 | Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& rTgTbT) { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 350 | rXgXbX = Sk4f::Load(matrix + 0); |
| 351 | rYgYbY = Sk4f::Load(matrix + 3); |
| 352 | rZgZbZ = Sk4f::Load(matrix + 6); |
| 353 | rTgTbT = Sk4f::Load(matrix + 9); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 354 | } |
| 355 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 356 | enum Order { |
| 357 | kRGBA_Order, |
| 358 | kBGRA_Order, |
| 359 | }; |
| 360 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 361 | static AI void set_rb_shifts(Order kOrder, int* kRShift, int* kBShift) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 362 | if (kRGBA_Order == kOrder) { |
| 363 | *kRShift = 0; |
| 364 | *kBShift = 16; |
| 365 | } else { |
| 366 | *kRShift = 16; |
| 367 | *kBShift = 0; |
| 368 | } |
| 369 | } |
| 370 | |
| 371 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 372 | static AI void load_rgb_from_tables(const uint32_t* src, |
| 373 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 374 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 375 | int kRShift, kGShift = 8, kBShift; |
| 376 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 377 | r = { srcTables[0][(src[0] >> kRShift) & 0xFF], |
| 378 | srcTables[0][(src[1] >> kRShift) & 0xFF], |
| 379 | srcTables[0][(src[2] >> kRShift) & 0xFF], |
| 380 | srcTables[0][(src[3] >> kRShift) & 0xFF], }; |
| 381 | g = { srcTables[1][(src[0] >> kGShift) & 0xFF], |
| 382 | srcTables[1][(src[1] >> kGShift) & 0xFF], |
| 383 | srcTables[1][(src[2] >> kGShift) & 0xFF], |
| 384 | srcTables[1][(src[3] >> kGShift) & 0xFF], }; |
| 385 | b = { srcTables[2][(src[0] >> kBShift) & 0xFF], |
| 386 | srcTables[2][(src[1] >> kBShift) & 0xFF], |
| 387 | srcTables[2][(src[2] >> kBShift) & 0xFF], |
| 388 | srcTables[2][(src[3] >> kBShift) & 0xFF], }; |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 389 | a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. |
| 390 | } |
| 391 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 392 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 393 | static AI void load_rgba_from_tables(const uint32_t* src, |
| 394 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 395 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 396 | int kRShift, kGShift = 8, kBShift; |
| 397 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 398 | r = { srcTables[0][(src[0] >> kRShift) & 0xFF], |
| 399 | srcTables[0][(src[1] >> kRShift) & 0xFF], |
| 400 | srcTables[0][(src[2] >> kRShift) & 0xFF], |
| 401 | srcTables[0][(src[3] >> kRShift) & 0xFF], }; |
msarett | 5414be0 | 2016-09-22 13:23:56 -0700 | [diff] [blame] | 402 | g = { srcTables[1][(src[0] >> kGShift) & 0xFF], |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 403 | srcTables[1][(src[1] >> kGShift) & 0xFF], |
| 404 | srcTables[1][(src[2] >> kGShift) & 0xFF], |
| 405 | srcTables[1][(src[3] >> kGShift) & 0xFF], }; |
| 406 | b = { srcTables[2][(src[0] >> kBShift) & 0xFF], |
| 407 | srcTables[2][(src[1] >> kBShift) & 0xFF], |
| 408 | srcTables[2][(src[2] >> kBShift) & 0xFF], |
| 409 | srcTables[2][(src[3] >> kBShift) & 0xFF], }; |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 410 | a = (1.0f / 255.0f) * SkNx_cast<float>(Sk4u::Load(src) >> 24); |
| 411 | } |
| 412 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 413 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 414 | static AI void load_rgb_linear(const uint32_t* src, Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 415 | const float* const[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 416 | int kRShift, kGShift = 8, kBShift; |
| 417 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 418 | r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF); |
| 419 | g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF); |
| 420 | b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF); |
msarett | be36277 | 2016-09-14 11:53:49 -0700 | [diff] [blame] | 421 | a = 0.0f; // Don't let the compiler complain that |a| is uninitialized. |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 422 | } |
| 423 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 424 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 425 | static AI void load_rgba_linear(const uint32_t* src, Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 426 | const float* const[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 427 | int kRShift, kGShift = 8, kBShift; |
| 428 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 429 | r = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kRShift) & 0xFF); |
| 430 | g = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kGShift) & 0xFF); |
| 431 | b = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> kBShift) & 0xFF); |
| 432 | a = (1.0f / 255.0f) * SkNx_cast<float>((Sk4u::Load(src) >> 24)); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 433 | } |
| 434 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 435 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 436 | static AI void load_rgb_from_tables_1(const uint32_t* src, |
| 437 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 438 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 439 | int kRShift, kGShift = 8, kBShift; |
| 440 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 441 | r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]); |
| 442 | g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]); |
| 443 | b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]); |
Matt Sarett | a9f64de | 2016-10-21 09:25:54 -0400 | [diff] [blame] | 444 | a = 0.0f; // Don't let MSAN complain that |a| is uninitialized. |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 445 | } |
| 446 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 447 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 448 | static AI void load_rgba_from_tables_1(const uint32_t* src, |
| 449 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 450 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 451 | int kRShift, kGShift = 8, kBShift; |
| 452 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 453 | r = Sk4f(srcTables[0][(*src >> kRShift) & 0xFF]); |
| 454 | g = Sk4f(srcTables[1][(*src >> kGShift) & 0xFF]); |
| 455 | b = Sk4f(srcTables[2][(*src >> kBShift) & 0xFF]); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 456 | a = (1.0f / 255.0f) * Sk4f(*src >> 24); |
| 457 | } |
| 458 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 459 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 460 | static AI void load_rgb_linear_1(const uint32_t* src, |
| 461 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 462 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 463 | int kRShift, kGShift = 8, kBShift; |
| 464 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 465 | r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF)); |
| 466 | g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF)); |
| 467 | b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF)); |
Matt Sarett | a9f64de | 2016-10-21 09:25:54 -0400 | [diff] [blame] | 468 | a = 0.0f; // Don't let MSAN complain that |a| is uninitialized. |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 469 | } |
| 470 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 471 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 472 | static AI void load_rgba_linear_1(const uint32_t* src, |
| 473 | Sk4f& r, Sk4f& g, Sk4f& b, Sk4f& a, |
| 474 | const float* const srcTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 475 | int kRShift, kGShift = 8, kBShift; |
| 476 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
| 477 | r = Sk4f((1.0f / 255.0f) * ((*src >> kRShift) & 0xFF)); |
| 478 | g = Sk4f((1.0f / 255.0f) * ((*src >> kGShift) & 0xFF)); |
| 479 | b = Sk4f((1.0f / 255.0f) * ((*src >> kBShift) & 0xFF)); |
| 480 | a = Sk4f((1.0f / 255.0f) * ((*src >> 24))); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 481 | } |
| 482 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 483 | static AI void transform_gamut(const Sk4f& r, const Sk4f& g, const Sk4f& b, const Sk4f& a, |
| 484 | const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, |
| 485 | Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 486 | dr = rXgXbX[0]*r + rYgYbY[0]*g + rZgZbZ[0]*b; |
| 487 | dg = rXgXbX[1]*r + rYgYbY[1]*g + rZgZbZ[1]*b; |
| 488 | db = rXgXbX[2]*r + rYgYbY[2]*g + rZgZbZ[2]*b; |
| 489 | da = a; |
| 490 | } |
| 491 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 492 | static AI void transform_gamut_1(const Sk4f& r, const Sk4f& g, const Sk4f& b, |
| 493 | const Sk4f& rXgXbX, const Sk4f& rYgYbY, const Sk4f& rZgZbZ, |
| 494 | Sk4f& rgba) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 495 | rgba = rXgXbX*r + rYgYbY*g + rZgZbZ*b; |
| 496 | } |
| 497 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 498 | static AI void translate_gamut(const Sk4f& rTgTbT, Sk4f& dr, Sk4f& dg, Sk4f& db) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 499 | dr = dr + rTgTbT[0]; |
| 500 | dg = dg + rTgTbT[1]; |
| 501 | db = db + rTgTbT[2]; |
| 502 | } |
| 503 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 504 | static AI void translate_gamut_1(const Sk4f& rTgTbT, Sk4f& rgba) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 505 | rgba = rgba + rTgTbT; |
| 506 | } |
| 507 | |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 508 | static AI void premultiply(Sk4f& dr, Sk4f& dg, Sk4f& db, const Sk4f& da, bool kClamp) { |
| 509 | if (kClamp) { |
Matt Sarett | 8b4b56a | 2016-12-04 16:08:14 -0500 | [diff] [blame] | 510 | dr = Sk4f::Min(dr, 1.0f); |
| 511 | dg = Sk4f::Min(dg, 1.0f); |
| 512 | db = Sk4f::Min(db, 1.0f); |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 513 | } |
| 514 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 515 | dr = da * dr; |
| 516 | dg = da * dg; |
| 517 | db = da * db; |
| 518 | } |
| 519 | |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 520 | static AI void premultiply_1(const Sk4f& a, Sk4f& rgba, bool kClamp) { |
| 521 | if (kClamp) { |
Matt Sarett | 8b4b56a | 2016-12-04 16:08:14 -0500 | [diff] [blame] | 522 | rgba = Sk4f::Min(rgba, 1.0f); |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 523 | } |
| 524 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 525 | rgba = a * rgba; |
| 526 | } |
| 527 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 528 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 529 | static AI void store_srgb(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 530 | const uint8_t* const[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 531 | int kRShift, kGShift = 8, kBShift; |
| 532 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 533 | dr = sk_linear_to_srgb_needs_trunc(dr); |
| 534 | dg = sk_linear_to_srgb_needs_trunc(dg); |
| 535 | db = sk_linear_to_srgb_needs_trunc(db); |
| 536 | |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 537 | dr = sk_clamp_0_255(dr); |
| 538 | dg = sk_clamp_0_255(dg); |
| 539 | db = sk_clamp_0_255(db); |
| 540 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 541 | Sk4i da = Sk4i::Load(src) & 0xFF000000; |
| 542 | |
| 543 | Sk4i rgba = (SkNx_cast<int>(dr) << kRShift) |
| 544 | | (SkNx_cast<int>(dg) << kGShift) |
| 545 | | (SkNx_cast<int>(db) << kBShift) |
| 546 | | (da ); |
| 547 | rgba.store(dst); |
| 548 | } |
| 549 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 550 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 551 | static AI void store_srgb_1(void* dst, const uint32_t* src, |
| 552 | Sk4f& rgba, const Sk4f&, |
| 553 | const uint8_t* const[3]) { |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 554 | rgba = sk_clamp_0_255(sk_linear_to_srgb_needs_trunc(rgba)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 555 | |
| 556 | uint32_t tmp; |
| 557 | SkNx_cast<uint8_t>(SkNx_cast<int32_t>(rgba)).store(&tmp); |
| 558 | tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 559 | if (kBGRA_Order == kOrder) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 560 | tmp = SkSwizzle_RB(tmp); |
| 561 | } |
| 562 | |
| 563 | *(uint32_t*)dst = tmp; |
| 564 | } |
| 565 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 566 | static AI Sk4f linear_to_2dot2(const Sk4f& x) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 567 | // x^(29/64) is a very good approximation of the true value, x^(1/2.2). |
| 568 | auto x2 = x.rsqrt(), // x^(-1/2) |
| 569 | x32 = x2.rsqrt().rsqrt().rsqrt().rsqrt(), // x^(-1/32) |
| 570 | x64 = x32.rsqrt(); // x^(+1/64) |
| 571 | |
| 572 | // 29 = 32 - 2 - 1 |
| 573 | return 255.0f * x2.invert() * x32 * x64.invert(); |
| 574 | } |
| 575 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 576 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 577 | static AI void store_2dot2(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 578 | const uint8_t* const[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 579 | int kRShift, kGShift = 8, kBShift; |
| 580 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 581 | dr = linear_to_2dot2(dr); |
| 582 | dg = linear_to_2dot2(dg); |
| 583 | db = linear_to_2dot2(db); |
| 584 | |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 585 | dr = sk_clamp_0_255(dr); |
| 586 | dg = sk_clamp_0_255(dg); |
| 587 | db = sk_clamp_0_255(db); |
| 588 | |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 589 | Sk4i da = Sk4i::Load(src) & 0xFF000000; |
| 590 | |
| 591 | Sk4i rgba = (Sk4f_round(dr) << kRShift) |
| 592 | | (Sk4f_round(dg) << kGShift) |
| 593 | | (Sk4f_round(db) << kBShift) |
| 594 | | (da ); |
| 595 | rgba.store(dst); |
| 596 | } |
| 597 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 598 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 599 | static AI void store_2dot2_1(void* dst, const uint32_t* src, |
| 600 | Sk4f& rgba, const Sk4f&, |
| 601 | const uint8_t* const[3]) { |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 602 | rgba = sk_clamp_0_255(linear_to_2dot2(rgba)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 603 | |
| 604 | uint32_t tmp; |
| 605 | SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); |
| 606 | tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 607 | if (kBGRA_Order == kOrder) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 608 | tmp = SkSwizzle_RB(tmp); |
| 609 | } |
| 610 | |
| 611 | *(uint32_t*)dst = tmp; |
| 612 | } |
| 613 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 614 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 615 | static AI void store_linear(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 616 | const uint8_t* const[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 617 | int kRShift, kGShift = 8, kBShift; |
| 618 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 619 | dr = sk_clamp_0_255(255.0f * dr); |
| 620 | dg = sk_clamp_0_255(255.0f * dg); |
| 621 | db = sk_clamp_0_255(255.0f * db); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 622 | |
| 623 | Sk4i da = Sk4i::Load(src) & 0xFF000000; |
| 624 | |
| 625 | Sk4i rgba = (Sk4f_round(dr) << kRShift) |
| 626 | | (Sk4f_round(dg) << kGShift) |
| 627 | | (Sk4f_round(db) << kBShift) |
| 628 | | (da ); |
| 629 | rgba.store(dst); |
| 630 | } |
| 631 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 632 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 633 | static AI void store_linear_1(void* dst, const uint32_t* src, |
| 634 | Sk4f& rgba, const Sk4f&, |
| 635 | const uint8_t* const[3]) { |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 636 | rgba = sk_clamp_0_255(255.0f * rgba); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 637 | |
| 638 | uint32_t tmp; |
| 639 | SkNx_cast<uint8_t>(Sk4f_round(rgba)).store(&tmp); |
| 640 | tmp = (*src & 0xFF000000) | (tmp & 0x00FFFFFF); |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 641 | if (kBGRA_Order == kOrder) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 642 | tmp = SkSwizzle_RB(tmp); |
| 643 | } |
| 644 | |
| 645 | *(uint32_t*)dst = tmp; |
| 646 | } |
| 647 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 648 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 649 | static AI void store_f16(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f& da, |
| 650 | const uint8_t* const[3]) { |
Mike Klein | 33cbfd7 | 2016-10-06 11:09:27 -0400 | [diff] [blame] | 651 | Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr), |
| 652 | SkFloatToHalf_finite_ftz(dg), |
| 653 | SkFloatToHalf_finite_ftz(db), |
| 654 | SkFloatToHalf_finite_ftz(da)); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 655 | } |
| 656 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 657 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 658 | static AI void store_f16_1(void* dst, const uint32_t* src, |
| 659 | Sk4f& rgba, const Sk4f& a, |
| 660 | const uint8_t* const[3]) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 661 | rgba = Sk4f(rgba[0], rgba[1], rgba[2], a[3]); |
mtklein | 8ae991e | 2016-08-22 13:20:18 -0700 | [diff] [blame] | 662 | SkFloatToHalf_finite_ftz(rgba).store((uint64_t*) dst); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 663 | } |
| 664 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 665 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 666 | static AI void store_f16_opaque(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, |
| 667 | Sk4f&, const uint8_t* const[3]) { |
Mike Klein | 33cbfd7 | 2016-10-06 11:09:27 -0400 | [diff] [blame] | 668 | Sk4h::Store4(dst, SkFloatToHalf_finite_ftz(dr), |
| 669 | SkFloatToHalf_finite_ftz(dg), |
| 670 | SkFloatToHalf_finite_ftz(db), |
| 671 | SK_Half1); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 672 | } |
| 673 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 674 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 675 | static AI void store_f16_1_opaque(void* dst, const uint32_t* src, |
| 676 | Sk4f& rgba, const Sk4f&, |
| 677 | const uint8_t* const[3]) { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 678 | uint64_t tmp; |
mtklein | 8ae991e | 2016-08-22 13:20:18 -0700 | [diff] [blame] | 679 | SkFloatToHalf_finite_ftz(rgba).store(&tmp); |
Matt Sarett | e980155 | 2017-01-09 09:14:28 -0500 | [diff] [blame] | 680 | tmp &= 0x0000FFFFFFFFFFFF; |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 681 | tmp |= static_cast<uint64_t>(SK_Half1) << 48; |
| 682 | *((uint64_t*) dst) = tmp; |
| 683 | } |
| 684 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 685 | template <Order kOrder> |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 686 | static AI void store_generic(void* dst, const uint32_t* src, Sk4f& dr, Sk4f& dg, Sk4f& db, Sk4f&, |
| 687 | const uint8_t* const dstTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 688 | int kRShift, kGShift = 8, kBShift; |
| 689 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 690 | dr = Sk4f::Min(Sk4f::Max(1023.0f * dr, 0.0f), 1023.0f); |
| 691 | dg = Sk4f::Min(Sk4f::Max(1023.0f * dg, 0.0f), 1023.0f); |
| 692 | db = Sk4f::Min(Sk4f::Max(1023.0f * db, 0.0f), 1023.0f); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 693 | |
| 694 | Sk4i ir = Sk4f_round(dr); |
| 695 | Sk4i ig = Sk4f_round(dg); |
| 696 | Sk4i ib = Sk4f_round(db); |
| 697 | |
| 698 | Sk4i da = Sk4i::Load(src) & 0xFF000000; |
| 699 | |
| 700 | uint32_t* dst32 = (uint32_t*) dst; |
| 701 | dst32[0] = dstTables[0][ir[0]] << kRShift |
| 702 | | dstTables[1][ig[0]] << kGShift |
| 703 | | dstTables[2][ib[0]] << kBShift |
| 704 | | da[0]; |
| 705 | dst32[1] = dstTables[0][ir[1]] << kRShift |
| 706 | | dstTables[1][ig[1]] << kGShift |
| 707 | | dstTables[2][ib[1]] << kBShift |
| 708 | | da[1]; |
| 709 | dst32[2] = dstTables[0][ir[2]] << kRShift |
| 710 | | dstTables[1][ig[2]] << kGShift |
| 711 | | dstTables[2][ib[2]] << kBShift |
| 712 | | da[2]; |
| 713 | dst32[3] = dstTables[0][ir[3]] << kRShift |
| 714 | | dstTables[1][ig[3]] << kGShift |
| 715 | | dstTables[2][ib[3]] << kBShift |
| 716 | | da[3]; |
| 717 | } |
| 718 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 719 | template <Order kOrder> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 720 | static AI void store_generic_1(void* dst, const uint32_t* src, |
| 721 | Sk4f& rgba, const Sk4f&, |
| 722 | const uint8_t* const dstTables[3]) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 723 | int kRShift, kGShift = 8, kBShift; |
| 724 | set_rb_shifts(kOrder, &kRShift, &kBShift); |
Matt Sarett | 17e4940 | 2016-12-01 20:28:35 +0000 | [diff] [blame] | 725 | rgba = Sk4f::Min(Sk4f::Max(1023.0f * rgba, 0.0f), 1023.0f); |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 726 | |
| 727 | Sk4i indices = Sk4f_round(rgba); |
| 728 | |
msarett | 9dc6cf6 | 2016-08-23 17:53:06 -0700 | [diff] [blame] | 729 | *((uint32_t*) dst) = dstTables[0][indices[0]] << kRShift |
| 730 | | dstTables[1][indices[1]] << kGShift |
| 731 | | dstTables[2][indices[2]] << kBShift |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 732 | | (*src & 0xFF000000); |
| 733 | } |
| 734 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 735 | typedef decltype(load_rgb_from_tables<kRGBA_Order> )* LoadFn; |
| 736 | typedef decltype(load_rgb_from_tables_1<kRGBA_Order>)* Load1Fn; |
| 737 | typedef decltype(store_generic<kRGBA_Order> )* StoreFn; |
| 738 | typedef decltype(store_generic_1<kRGBA_Order> )* Store1Fn; |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 739 | |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 740 | enum SrcFormat { |
| 741 | kRGBA_8888_Linear_SrcFormat, |
| 742 | kRGBA_8888_Table_SrcFormat, |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 743 | kBGRA_8888_Linear_SrcFormat, |
| 744 | kBGRA_8888_Table_SrcFormat, |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 745 | }; |
| 746 | |
| 747 | enum DstFormat { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 748 | kRGBA_8888_Linear_DstFormat, |
| 749 | kRGBA_8888_SRGB_DstFormat, |
| 750 | kRGBA_8888_2Dot2_DstFormat, |
| 751 | kRGBA_8888_Table_DstFormat, |
| 752 | kBGRA_8888_Linear_DstFormat, |
| 753 | kBGRA_8888_SRGB_DstFormat, |
| 754 | kBGRA_8888_2Dot2_DstFormat, |
| 755 | kBGRA_8888_Table_DstFormat, |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 756 | kF16_Linear_DstFormat, |
| 757 | }; |
| 758 | |
| 759 | template <SrcFormat kSrc, |
| 760 | DstFormat kDst, |
| 761 | SkAlphaType kAlphaType, |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 762 | ColorSpaceMatch kCSM> |
Matt Sarett | 5934646 | 2016-10-24 16:51:45 -0400 | [diff] [blame] | 763 | static void color_xform_RGBA(void* dst, const void* vsrc, int len, |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 764 | const float* const srcTables[3], const float matrix[13], |
Matt Sarett | 5934646 | 2016-10-24 16:51:45 -0400 | [diff] [blame] | 765 | const uint8_t* const dstTables[3]) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 766 | LoadFn load; |
| 767 | Load1Fn load_1; |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 768 | const bool kLoadAlpha = (kPremul_SkAlphaType == kAlphaType) || |
Matt Sarett | e980155 | 2017-01-09 09:14:28 -0500 | [diff] [blame] | 769 | (kF16_Linear_DstFormat == kDst && kOpaque_SkAlphaType != kAlphaType); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 770 | switch (kSrc) { |
| 771 | case kRGBA_8888_Linear_SrcFormat: |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 772 | if (kLoadAlpha) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 773 | load = load_rgba_linear<kRGBA_Order>; |
| 774 | load_1 = load_rgba_linear_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 775 | } else { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 776 | load = load_rgb_linear<kRGBA_Order>; |
| 777 | load_1 = load_rgb_linear_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 778 | } |
| 779 | break; |
| 780 | case kRGBA_8888_Table_SrcFormat: |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 781 | if (kLoadAlpha) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 782 | load = load_rgba_from_tables<kRGBA_Order>; |
| 783 | load_1 = load_rgba_from_tables_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 784 | } else { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 785 | load = load_rgb_from_tables<kRGBA_Order>; |
| 786 | load_1 = load_rgb_from_tables_1<kRGBA_Order>; |
| 787 | } |
| 788 | break; |
| 789 | case kBGRA_8888_Linear_SrcFormat: |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 790 | if (kLoadAlpha) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 791 | load = load_rgba_linear<kBGRA_Order>; |
| 792 | load_1 = load_rgba_linear_1<kBGRA_Order>; |
| 793 | } else { |
| 794 | load = load_rgb_linear<kBGRA_Order>; |
| 795 | load_1 = load_rgb_linear_1<kBGRA_Order>; |
| 796 | } |
| 797 | break; |
| 798 | case kBGRA_8888_Table_SrcFormat: |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 799 | if (kLoadAlpha) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 800 | load = load_rgba_from_tables<kBGRA_Order>; |
| 801 | load_1 = load_rgba_from_tables_1<kBGRA_Order>; |
| 802 | } else { |
| 803 | load = load_rgb_from_tables<kBGRA_Order>; |
| 804 | load_1 = load_rgb_from_tables_1<kBGRA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 805 | } |
| 806 | break; |
| 807 | } |
| 808 | |
| 809 | StoreFn store; |
| 810 | Store1Fn store_1; |
| 811 | size_t sizeOfDstPixel; |
| 812 | switch (kDst) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 813 | case kRGBA_8888_Linear_DstFormat: |
| 814 | store = store_linear<kRGBA_Order>; |
| 815 | store_1 = store_linear_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 816 | sizeOfDstPixel = 4; |
| 817 | break; |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 818 | case kRGBA_8888_SRGB_DstFormat: |
| 819 | store = store_srgb<kRGBA_Order>; |
| 820 | store_1 = store_srgb_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 821 | sizeOfDstPixel = 4; |
| 822 | break; |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 823 | case kRGBA_8888_2Dot2_DstFormat: |
| 824 | store = store_2dot2<kRGBA_Order>; |
| 825 | store_1 = store_2dot2_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 826 | sizeOfDstPixel = 4; |
| 827 | break; |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 828 | case kRGBA_8888_Table_DstFormat: |
| 829 | store = store_generic<kRGBA_Order>; |
| 830 | store_1 = store_generic_1<kRGBA_Order>; |
| 831 | sizeOfDstPixel = 4; |
| 832 | break; |
| 833 | case kBGRA_8888_Linear_DstFormat: |
| 834 | store = store_linear<kBGRA_Order>; |
| 835 | store_1 = store_linear_1<kBGRA_Order>; |
| 836 | sizeOfDstPixel = 4; |
| 837 | break; |
| 838 | case kBGRA_8888_SRGB_DstFormat: |
| 839 | store = store_srgb<kBGRA_Order>; |
| 840 | store_1 = store_srgb_1<kBGRA_Order>; |
| 841 | sizeOfDstPixel = 4; |
| 842 | break; |
| 843 | case kBGRA_8888_2Dot2_DstFormat: |
| 844 | store = store_2dot2<kBGRA_Order>; |
| 845 | store_1 = store_2dot2_1<kBGRA_Order>; |
| 846 | sizeOfDstPixel = 4; |
| 847 | break; |
| 848 | case kBGRA_8888_Table_DstFormat: |
| 849 | store = store_generic<kBGRA_Order>; |
| 850 | store_1 = store_generic_1<kBGRA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 851 | sizeOfDstPixel = 4; |
| 852 | break; |
| 853 | case kF16_Linear_DstFormat: |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 854 | store = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_opaque<kRGBA_Order> : |
| 855 | store_f16<kRGBA_Order>; |
| 856 | store_1 = (kOpaque_SkAlphaType == kAlphaType) ? store_f16_1_opaque<kRGBA_Order> : |
| 857 | store_f16_1<kRGBA_Order>; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 858 | sizeOfDstPixel = 8; |
| 859 | break; |
| 860 | } |
| 861 | |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 862 | // We always clamp before converting to 8888 outputs (because we have to). |
| 863 | // In these cases, we also need a clamp before the premul step to make sure |
| 864 | // R, G, B are not logically greater than A. |
| 865 | const bool kClamp = kRGBA_8888_Linear_DstFormat == kDst || |
| 866 | kRGBA_8888_SRGB_DstFormat == kDst || |
| 867 | kRGBA_8888_2Dot2_DstFormat == kDst || |
| 868 | kRGBA_8888_Table_DstFormat == kDst; |
| 869 | |
Matt Sarett | d478a99 | 2016-10-14 13:04:55 -0400 | [diff] [blame] | 870 | const uint32_t* src = (const uint32_t*) vsrc; |
| 871 | Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; |
| 872 | load_matrix(matrix, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); |
| 873 | |
| 874 | if (len >= 4) { |
| 875 | // Naively this would be a loop of load-transform-store, but we found it faster to |
| 876 | // move the N+1th load ahead of the Nth store. We don't bother doing this for N<4. |
| 877 | Sk4f r, g, b, a; |
| 878 | load(src, r, g, b, a, srcTables); |
| 879 | src += 4; |
| 880 | len -= 4; |
| 881 | |
| 882 | Sk4f dr, dg, db, da; |
| 883 | while (len >= 4) { |
| 884 | if (kNone_ColorSpaceMatch == kCSM) { |
| 885 | transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
| 886 | translate_gamut(rTgTbT, dr, dg, db); |
| 887 | } else { |
| 888 | dr = r; |
| 889 | dg = g; |
| 890 | db = b; |
| 891 | da = a; |
| 892 | } |
| 893 | |
| 894 | if (kPremul_SkAlphaType == kAlphaType) { |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 895 | premultiply(dr, dg, db, da, kClamp); |
Matt Sarett | d478a99 | 2016-10-14 13:04:55 -0400 | [diff] [blame] | 896 | } |
| 897 | |
| 898 | load(src, r, g, b, a, srcTables); |
| 899 | |
| 900 | store(dst, src - 4, dr, dg, db, da, dstTables); |
| 901 | dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); |
| 902 | src += 4; |
| 903 | len -= 4; |
| 904 | } |
| 905 | |
| 906 | if (kNone_ColorSpaceMatch == kCSM) { |
| 907 | transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
| 908 | translate_gamut(rTgTbT, dr, dg, db); |
| 909 | } else { |
| 910 | dr = r; |
| 911 | dg = g; |
| 912 | db = b; |
| 913 | da = a; |
| 914 | } |
| 915 | |
| 916 | if (kPremul_SkAlphaType == kAlphaType) { |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 917 | premultiply(dr, dg, db, da, kClamp); |
Matt Sarett | d478a99 | 2016-10-14 13:04:55 -0400 | [diff] [blame] | 918 | } |
| 919 | |
| 920 | store(dst, src - 4, dr, dg, db, da, dstTables); |
| 921 | dst = SkTAddOffset<void>(dst, 4 * sizeOfDstPixel); |
| 922 | } |
| 923 | |
| 924 | while (len > 0) { |
| 925 | Sk4f r, g, b, a; |
| 926 | load_1(src, r, g, b, a, srcTables); |
| 927 | |
| 928 | Sk4f rgba; |
| 929 | if (kNone_ColorSpaceMatch == kCSM) { |
| 930 | transform_gamut_1(r, g, b, rXgXbX, rYgYbY, rZgZbZ, rgba); |
| 931 | translate_gamut_1(rTgTbT, rgba); |
| 932 | } else { |
| 933 | rgba = Sk4f(r[0], g[0], b[0], a[0]); |
| 934 | } |
| 935 | |
| 936 | if (kPremul_SkAlphaType == kAlphaType) { |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 937 | premultiply_1(a, rgba, kClamp); |
Matt Sarett | d478a99 | 2016-10-14 13:04:55 -0400 | [diff] [blame] | 938 | } |
| 939 | |
| 940 | store_1(dst, src, rgba, a, dstTables); |
| 941 | |
| 942 | src += 1; |
| 943 | len -= 1; |
| 944 | dst = SkTAddOffset<void>(dst, sizeOfDstPixel); |
| 945 | } |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 946 | } |
| 947 | |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 948 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 949 | |
raftias | 2563601 | 2016-11-11 15:27:39 -0800 | [diff] [blame] | 950 | static AI int num_tables(SkColorSpace_XYZ* space) { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 951 | switch (space->gammaNamed()) { |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 952 | case kSRGB_SkGammaNamed: |
| 953 | case k2Dot2Curve_SkGammaNamed: |
| 954 | case kLinear_SkGammaNamed: |
| 955 | return 0; |
| 956 | default: { |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 957 | const SkGammas* gammas = space->gammas(); |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 958 | SkASSERT(gammas); |
| 959 | |
| 960 | bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && |
| 961 | (gammas->data(0) == gammas->data(1)) && |
| 962 | (gammas->type(0) == gammas->type(2)) && |
| 963 | (gammas->data(0) == gammas->data(2)); |
| 964 | |
| 965 | // It's likely that each component will have the same gamma. In this case, |
| 966 | // we only need to build one table. |
| 967 | return gammasAreMatching ? 1 : 3; |
| 968 | } |
| 969 | } |
| 970 | } |
| 971 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 972 | template <ColorSpaceMatch kCSM> |
| 973 | SkColorSpaceXform_XYZ<kCSM> |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 974 | ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst, |
| 975 | SkColorSpace_XYZ* dstSpace) |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 976 | { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 977 | fSrcToDst[ 0] = srcToDst.get(0, 0); |
| 978 | fSrcToDst[ 1] = srcToDst.get(1, 0); |
| 979 | fSrcToDst[ 2] = srcToDst.get(2, 0); |
| 980 | fSrcToDst[ 3] = srcToDst.get(0, 1); |
| 981 | fSrcToDst[ 4] = srcToDst.get(1, 1); |
| 982 | fSrcToDst[ 5] = srcToDst.get(2, 1); |
| 983 | fSrcToDst[ 6] = srcToDst.get(0, 2); |
| 984 | fSrcToDst[ 7] = srcToDst.get(1, 2); |
| 985 | fSrcToDst[ 8] = srcToDst.get(2, 2); |
| 986 | fSrcToDst[ 9] = srcToDst.get(0, 3); |
| 987 | fSrcToDst[10] = srcToDst.get(1, 3); |
| 988 | fSrcToDst[11] = srcToDst.get(2, 3); |
| 989 | fSrcToDst[12] = 0.0f; |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 990 | |
msarett | 4be0e7c | 2016-09-22 07:02:24 -0700 | [diff] [blame] | 991 | const int numSrcTables = num_tables(srcSpace); |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 992 | const size_t srcEntries = numSrcTables * 256; |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 993 | const bool srcGammasAreMatching = (1 >= numSrcTables); |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 994 | fSrcStorage.reset(srcEntries); |
| 995 | build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLinear, |
| 996 | srcGammasAreMatching); |
| 997 | |
| 998 | const int numDstTables = num_tables(dstSpace); |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 999 | dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1000 | |
| 1001 | if (srcSpace->gammaIsLinear()) { |
| 1002 | fSrcGamma = kLinear_SrcGamma; |
| 1003 | } else if (kSRGB_SkGammaNamed == srcSpace->gammaNamed()) { |
| 1004 | fSrcGamma = kSRGB_SrcGamma; |
| 1005 | } else { |
| 1006 | fSrcGamma = kTable_SrcGamma; |
| 1007 | } |
| 1008 | |
| 1009 | switch (dstSpace->gammaNamed()) { |
| 1010 | case kSRGB_SkGammaNamed: |
| 1011 | fDstGamma = kSRGB_DstGamma; |
| 1012 | break; |
| 1013 | case k2Dot2Curve_SkGammaNamed: |
| 1014 | fDstGamma = k2Dot2_DstGamma; |
| 1015 | break; |
| 1016 | case kLinear_SkGammaNamed: |
| 1017 | fDstGamma = kLinear_DstGamma; |
| 1018 | break; |
| 1019 | default: |
| 1020 | fDstGamma = kTable_DstGamma; |
| 1021 | break; |
| 1022 | } |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 1023 | } |
| 1024 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 1025 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 1026 | |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1027 | template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 1028 | static AI bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaType alphaType, |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1029 | const float* const srcTables[3], const float matrix[13], |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 1030 | const uint8_t* const dstTables[3]) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1031 | switch (alphaType) { |
| 1032 | case kOpaque_SkAlphaType: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1033 | color_xform_RGBA<kSrc, kDst, kOpaque_SkAlphaType, kCSM> |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1034 | (dst, src, len, srcTables, matrix, dstTables); |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1035 | return true; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1036 | case kPremul_SkAlphaType: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1037 | color_xform_RGBA<kSrc, kDst, kPremul_SkAlphaType, kCSM> |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1038 | (dst, src, len, srcTables, matrix, dstTables); |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1039 | return true; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1040 | case kUnpremul_SkAlphaType: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1041 | color_xform_RGBA<kSrc, kDst, kUnpremul_SkAlphaType, kCSM> |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1042 | (dst, src, len, srcTables, matrix, dstTables); |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1043 | return true; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1044 | default: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1045 | return false; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1046 | } |
| 1047 | } |
| 1048 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1049 | template <DstFormat kDst, ColorSpaceMatch kCSM> |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 1050 | static AI bool apply_set_src(void* dst, const void* src, int len, SkAlphaType alphaType, |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1051 | const float* const srcTables[3], const float matrix[13], |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 1052 | const uint8_t* const dstTables[3], |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1053 | SkColorSpaceXform::ColorFormat srcColorFormat, |
| 1054 | SrcGamma srcGamma) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1055 | switch (srcColorFormat) { |
| 1056 | case SkColorSpaceXform::kRGBA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1057 | switch (srcGamma) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1058 | case kLinear_SrcGamma: |
| 1059 | return apply_set_alpha<kRGBA_8888_Linear_SrcFormat, kDst, kCSM> |
| 1060 | (dst, src, len, alphaType, nullptr, matrix, dstTables); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1061 | default: |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1062 | return apply_set_alpha<kRGBA_8888_Table_SrcFormat, kDst, kCSM> |
| 1063 | (dst, src, len, alphaType, srcTables, matrix, dstTables); |
| 1064 | } |
| 1065 | case SkColorSpaceXform::kBGRA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1066 | switch (srcGamma) { |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1067 | case kLinear_SrcGamma: |
| 1068 | return apply_set_alpha<kBGRA_8888_Linear_SrcFormat, kDst, kCSM> |
| 1069 | (dst, src, len, alphaType, nullptr, matrix, dstTables); |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1070 | default: |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1071 | return apply_set_alpha<kBGRA_8888_Table_SrcFormat, kDst, kCSM> |
| 1072 | (dst, src, len, alphaType, srcTables, matrix, dstTables); |
| 1073 | } |
| 1074 | default: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1075 | return false; |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1076 | } |
| 1077 | } |
| 1078 | |
Matt Sarett | df303a6 | 2016-10-24 11:38:08 -0400 | [diff] [blame] | 1079 | #undef AI |
| 1080 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1081 | template <ColorSpaceMatch kCSM> |
| 1082 | bool SkColorSpaceXform_XYZ<kCSM> |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1083 | ::onApply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, const void* src, |
| 1084 | int len, SkAlphaType alphaType) const |
msarett | 3418c0e | 2016-07-25 18:23:18 -0700 | [diff] [blame] | 1085 | { |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 1086 | if (kFull_ColorSpaceMatch == kCSM) { |
Matt Sarett | abf8ba3 | 2016-12-01 17:02:07 -0500 | [diff] [blame] | 1087 | if (kPremul_SkAlphaType != alphaType) { |
| 1088 | if ((kRGBA_8888_ColorFormat == dstColorFormat && |
| 1089 | kRGBA_8888_ColorFormat == srcColorFormat) || |
| 1090 | (kBGRA_8888_ColorFormat == dstColorFormat && |
| 1091 | kBGRA_8888_ColorFormat == srcColorFormat)) |
| 1092 | { |
| 1093 | memcpy(dst, src, len * sizeof(uint32_t)); |
| 1094 | return true; |
| 1095 | } |
| 1096 | if ((kRGBA_8888_ColorFormat == dstColorFormat && |
| 1097 | kBGRA_8888_ColorFormat == srcColorFormat) || |
| 1098 | (kBGRA_8888_ColorFormat == dstColorFormat && |
| 1099 | kRGBA_8888_ColorFormat == srcColorFormat)) |
| 1100 | { |
| 1101 | SkOpts::RGBA_to_BGRA((uint32_t*) dst, src, len); |
| 1102 | return true; |
| 1103 | } |
msarett | 200877e | 2016-08-15 08:10:44 -0700 | [diff] [blame] | 1104 | } |
| 1105 | } |
| 1106 | |
Matt Sarett | 7a090c4 | 2017-01-17 12:22:48 -0500 | [diff] [blame^] | 1107 | if (kRGBA_F32_ColorFormat == dstColorFormat || |
| 1108 | kRGBA_U16_BE_ColorFormat == srcColorFormat || |
| 1109 | kRGB_U16_BE_ColorFormat == srcColorFormat) |
| 1110 | { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1111 | return this->applyPipeline(dstColorFormat, dst, srcColorFormat, src, len, alphaType); |
| 1112 | } |
| 1113 | |
msarett | c044461 | 2016-09-16 11:45:58 -0700 | [diff] [blame] | 1114 | switch (dstColorFormat) { |
| 1115 | case kRGBA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1116 | switch (fDstGamma) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1117 | case kLinear_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1118 | return apply_set_src<kRGBA_8888_Linear_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1119 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1120 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1121 | case kSRGB_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1122 | return apply_set_src<kRGBA_8888_SRGB_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1123 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1124 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1125 | case k2Dot2_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1126 | return apply_set_src<kRGBA_8888_2Dot2_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1127 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1128 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1129 | case kTable_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1130 | return apply_set_src<kRGBA_8888_Table_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1131 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1132 | srcColorFormat, fSrcGamma); |
msarett | d1ec89b | 2016-08-03 12:59:27 -0700 | [diff] [blame] | 1133 | } |
msarett | c044461 | 2016-09-16 11:45:58 -0700 | [diff] [blame] | 1134 | case kBGRA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1135 | switch (fDstGamma) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1136 | case kLinear_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1137 | return apply_set_src<kBGRA_8888_Linear_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1138 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1139 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1140 | case kSRGB_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1141 | return apply_set_src<kBGRA_8888_SRGB_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1142 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1143 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1144 | case k2Dot2_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1145 | return apply_set_src<kBGRA_8888_2Dot2_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1146 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1147 | srcColorFormat, fSrcGamma); |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1148 | case kTable_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1149 | return apply_set_src<kBGRA_8888_Table_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1150 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, fDstGammaTables, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1151 | srcColorFormat, fSrcGamma); |
msarett | d1ec89b | 2016-08-03 12:59:27 -0700 | [diff] [blame] | 1152 | } |
msarett | c044461 | 2016-09-16 11:45:58 -0700 | [diff] [blame] | 1153 | case kRGBA_F16_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1154 | switch (fDstGamma) { |
msarett | 8bbcd5a | 2016-09-14 07:06:08 -0700 | [diff] [blame] | 1155 | case kLinear_DstGamma: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1156 | return apply_set_src<kF16_Linear_DstFormat, kCSM> |
msarett | cf7b877 | 2016-09-22 12:37:04 -0700 | [diff] [blame] | 1157 | (dst, src, len, alphaType, fSrcGammaTables, fSrcToDst, nullptr, |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1158 | srcColorFormat, fSrcGamma); |
msarett | d1ec89b | 2016-08-03 12:59:27 -0700 | [diff] [blame] | 1159 | default: |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1160 | return false; |
msarett | d1ec89b | 2016-08-03 12:59:27 -0700 | [diff] [blame] | 1161 | } |
| 1162 | default: |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1163 | SkASSERT(false); |
msarett | 31d097e8 | 2016-10-11 12:15:03 -0700 | [diff] [blame] | 1164 | return false; |
msarett | d1ec89b | 2016-08-03 12:59:27 -0700 | [diff] [blame] | 1165 | } |
msarett | 9ce3a54 | 2016-07-15 13:54:38 -0700 | [diff] [blame] | 1166 | } |
msarett | 9dc6cf6 | 2016-08-23 17:53:06 -0700 | [diff] [blame] | 1167 | |
Matt Sarett | f489886 | 2016-10-16 10:20:41 -0400 | [diff] [blame] | 1168 | bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, |
| 1169 | const void* src, int len, SkAlphaType alphaType) const { |
| 1170 | return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcColorFormat, src, len, |
| 1171 | alphaType); |
| 1172 | } |
| 1173 | |
msarett | 7bbda99 | 2016-09-14 11:02:04 -0700 | [diff] [blame] | 1174 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 1175 | |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1176 | template <ColorSpaceMatch kCSM> |
| 1177 | bool SkColorSpaceXform_XYZ<kCSM> |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1178 | ::applyPipeline(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, |
| 1179 | const void* src, int len, SkAlphaType alphaType) const { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1180 | SkRasterPipeline pipeline; |
| 1181 | |
| 1182 | LoadTablesContext loadTables; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1183 | switch (srcColorFormat) { |
| 1184 | case kRGBA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1185 | if (kLinear_SrcGamma == fSrcGamma) { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1186 | pipeline.append(SkRasterPipeline::load_8888, &src); |
| 1187 | } else { |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1188 | loadTables.fSrc = src; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1189 | loadTables.fR = fSrcGammaTables[0]; |
| 1190 | loadTables.fG = fSrcGammaTables[1]; |
| 1191 | loadTables.fB = fSrcGammaTables[2]; |
| 1192 | pipeline.append(SkRasterPipeline::load_tables, &loadTables); |
| 1193 | } |
| 1194 | |
| 1195 | break; |
| 1196 | case kBGRA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1197 | if (kLinear_SrcGamma == fSrcGamma) { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1198 | pipeline.append(SkRasterPipeline::load_8888, &src); |
| 1199 | } else { |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1200 | loadTables.fSrc = src; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1201 | loadTables.fR = fSrcGammaTables[2]; |
| 1202 | loadTables.fG = fSrcGammaTables[1]; |
| 1203 | loadTables.fB = fSrcGammaTables[0]; |
| 1204 | pipeline.append(SkRasterPipeline::load_tables, &loadTables); |
| 1205 | } |
| 1206 | |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1207 | pipeline.append(SkRasterPipeline::swap_rb); |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1208 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1209 | case kRGBA_U16_BE_ColorFormat: |
| 1210 | switch (fSrcGamma) { |
| 1211 | case kLinear_SrcGamma: |
| 1212 | pipeline.append(SkRasterPipeline::load_u16_be, &src); |
| 1213 | break; |
| 1214 | case kSRGB_SrcGamma: |
| 1215 | pipeline.append(SkRasterPipeline::load_u16_be, &src); |
| 1216 | pipeline.append_from_srgb(kUnpremul_SkAlphaType); |
| 1217 | break; |
| 1218 | case kTable_SrcGamma: |
| 1219 | loadTables.fSrc = src; |
| 1220 | loadTables.fR = fSrcGammaTables[0]; |
| 1221 | loadTables.fG = fSrcGammaTables[1]; |
| 1222 | loadTables.fB = fSrcGammaTables[2]; |
| 1223 | pipeline.append(SkRasterPipeline::load_tables_u16_be, &loadTables); |
| 1224 | break; |
| 1225 | } |
| 1226 | break; |
Matt Sarett | 7a090c4 | 2017-01-17 12:22:48 -0500 | [diff] [blame^] | 1227 | case kRGB_U16_BE_ColorFormat: |
| 1228 | switch (fSrcGamma) { |
| 1229 | case kLinear_SrcGamma: |
| 1230 | pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src); |
| 1231 | break; |
| 1232 | case kSRGB_SrcGamma: |
| 1233 | pipeline.append(SkRasterPipeline::load_rgb_u16_be, &src); |
| 1234 | pipeline.append_from_srgb(kUnpremul_SkAlphaType); |
| 1235 | break; |
| 1236 | case kTable_SrcGamma: |
| 1237 | loadTables.fSrc = src; |
| 1238 | loadTables.fR = fSrcGammaTables[0]; |
| 1239 | loadTables.fG = fSrcGammaTables[1]; |
| 1240 | loadTables.fB = fSrcGammaTables[2]; |
| 1241 | pipeline.append(SkRasterPipeline::load_tables_rgb_u16_be, &loadTables); |
| 1242 | break; |
| 1243 | } |
| 1244 | break; |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1245 | default: |
| 1246 | return false; |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1247 | } |
| 1248 | |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1249 | if (kNone_ColorSpaceMatch == kCSM) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1250 | pipeline.append(SkRasterPipeline::matrix_3x4, fSrcToDst); |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1251 | |
Mike Klein | 5e15961 | 2016-12-01 16:39:21 -0500 | [diff] [blame] | 1252 | if (kRGBA_8888_ColorFormat == dstColorFormat || kBGRA_8888_ColorFormat == dstColorFormat) { |
| 1253 | bool need_clamp_0, need_clamp_1; |
| 1254 | analyze_3x4_matrix(fSrcToDst, &need_clamp_0, &need_clamp_1); |
| 1255 | |
| 1256 | if (need_clamp_0) { pipeline.append(SkRasterPipeline::clamp_0); } |
| 1257 | if (need_clamp_1) { pipeline.append(SkRasterPipeline::clamp_1); } |
| 1258 | } |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1259 | } |
| 1260 | |
| 1261 | if (kPremul_SkAlphaType == alphaType) { |
| 1262 | pipeline.append(SkRasterPipeline::premul); |
| 1263 | } |
| 1264 | |
| 1265 | StoreTablesContext storeTables; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1266 | switch (fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1267 | case kSRGB_DstGamma: |
| 1268 | pipeline.append(SkRasterPipeline::to_srgb); |
| 1269 | break; |
| 1270 | case k2Dot2_DstGamma: |
| 1271 | pipeline.append(SkRasterPipeline::to_2dot2); |
| 1272 | break; |
| 1273 | default: |
| 1274 | break; |
| 1275 | } |
| 1276 | |
| 1277 | switch (dstColorFormat) { |
| 1278 | case kRGBA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1279 | if (kTable_DstGamma == fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1280 | storeTables.fDst = (uint32_t*) dst; |
| 1281 | storeTables.fR = fDstGammaTables[0]; |
| 1282 | storeTables.fG = fDstGammaTables[1]; |
| 1283 | storeTables.fB = fDstGammaTables[2]; |
| 1284 | storeTables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize; |
| 1285 | pipeline.append(SkRasterPipeline::store_tables, &storeTables); |
| 1286 | } else { |
| 1287 | pipeline.append(SkRasterPipeline::store_8888, &dst); |
| 1288 | } |
| 1289 | break; |
| 1290 | case kBGRA_8888_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1291 | if (kTable_DstGamma == fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1292 | storeTables.fDst = (uint32_t*) dst; |
| 1293 | storeTables.fR = fDstGammaTables[2]; |
| 1294 | storeTables.fG = fDstGammaTables[1]; |
| 1295 | storeTables.fB = fDstGammaTables[0]; |
| 1296 | storeTables.fCount = SkColorSpaceXform_Base::kDstGammaTableSize; |
| 1297 | pipeline.append(SkRasterPipeline::swap_rb); |
| 1298 | pipeline.append(SkRasterPipeline::store_tables, &storeTables); |
| 1299 | } else { |
| 1300 | pipeline.append(SkRasterPipeline::swap_rb); |
| 1301 | pipeline.append(SkRasterPipeline::store_8888, &dst); |
| 1302 | } |
| 1303 | break; |
| 1304 | case kRGBA_F16_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1305 | if (kLinear_DstGamma != fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1306 | return false; |
| 1307 | } |
| 1308 | pipeline.append(SkRasterPipeline::store_f16, &dst); |
| 1309 | break; |
| 1310 | case kRGBA_F32_ColorFormat: |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1311 | if (kLinear_DstGamma != fDstGamma) { |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1312 | return false; |
| 1313 | } |
| 1314 | pipeline.append(SkRasterPipeline::store_f32, &dst); |
| 1315 | break; |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1316 | default: |
| 1317 | return false; |
Matt Sarett | f6878ba | 2016-12-01 14:46:12 -0500 | [diff] [blame] | 1318 | } |
| 1319 | |
| 1320 | pipeline.run(0, 0, len); |
| 1321 | return true; |
| 1322 | } |
| 1323 | |
| 1324 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 1325 | |
raftias | 9488833 | 2016-10-18 10:02:51 -0700 | [diff] [blame] | 1326 | std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) { |
Matt Sarett | 26a0543 | 2017-01-04 16:54:55 -0500 | [diff] [blame] | 1327 | return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ |
Matt Sarett | 379938e | 2017-01-12 18:34:29 -0500 | [diff] [blame] | 1328 | <kNone_ColorSpaceMatch>(space, SkMatrix::I(), space)); |
msarett | 9dc6cf6 | 2016-08-23 17:53:06 -0700 | [diff] [blame] | 1329 | } |